15天学会爬虫 第五天

版权声明:转载请附带我的链接,谢谢! https://blog.csdn.net/weixin_41950282/article/details/86484362

爬虫

第五天

多线程

线程的创建和运行

import multiprocessing

def task(num):
    pass
p1 = multiprocessing.Process(target = task)
p1.start()

守护线程

一般情况下,主线程代码执行完毕后不会结束,会等待所有子线程任务结束后才结束
如果将子线程设置为守护线程,意味着:主线程代码执行完毕,主线程和子线程一起立即结束

t.setDaemom(True)

多线程的队列

from queue import Queue

q = Queue()
q.put() # 数据放入队列,队列计数+1
q.get() # 从队列中取出数据,队列计数不变
q.task_done() # 和q.gert()配合使用,队列计数-1
q.join() # 阻塞住线程

多进程

进程的创建和运行

import multiprocessing

def task(num):
    pass
p1 = multiprocessing
p1.start()

守护进程

将子进程设置为守护进程后,主进程代码执行完毕,主进程和子进程一起结束

p1.deamon=True

多进程的队列

from multiprocessing import JoinableQueue as Queue

线程池

使用线程池多好处

  • 降低资源消耗.通过重复利用已经创建的线程降低线程创建和销毁造成多消耗
  • 提高响应速度.当任务到达时,任务可以直接执行,而不需要等待新线程的创建
  • 提高线程的可管理性.线程时稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性
  • 使用线程池可以进行统一的分配,调优和监控

线程池的用法

from multiprocessing.dummy import Pool

def task():
    pass
pool = Pool(5) # 线程池中子线程的最大数量,当前为5
pool.apply_async(func=task,args=(,)) # 发布任务,交给线程池的子线程去执行,只是发布
pool.close() # 关闭线程池,不在接收信多任务,不是销毁线程池
pool.join() # 阻塞主线程,等待子线程中所有的任务结束

线程池的回调:
当不清楚线程池需要做的任务数量时,可以使用线程池的回调

def _callback(temp):
    print("---之前的线程任务执行完毕---")
pool.apply_async(func=task,callback=_callback) # 发布任务,交给线程池的子线程去执行,只是发布,当子线程执行完毕时,会自动调用callback

协程池

import gevent.monkey

gevent.monkey.patch_all()
# 协程池
from gevent.pool import Pool
from queue import Queue

# 协程池pool没有close的方法

GIL锁

全局解释器锁(GIL)是cpython解释器中的,限制了多线程,导致统一时刻只有一个线程被调用,而且不能充分发挥CPU多核的特性

GIL的步骤

  • 切换到一个线程
  • 设置GIL锁
  • 执行指定字节数量的代码
    • 代码执行完毕
    • 遇到延迟操作 「time.sleep(), socket.accept(), socket.connect()」等
  • 释放GIL锁
  • 切换到其他线程继续执行

并发和并行

  • 有多核心,每个核心执行一个任务,任务数量 <= 核心数,此时并行
  • 任务数量 >= 核心数此时并发

猜你喜欢

转载自blog.csdn.net/weixin_41950282/article/details/86484362