python 多线程与线程池原理

 

多线程:在同一个时间做多件事

守护线程:如果在程序中将子线程设置为守护线程,则该子线程会在主线程结束时自动退出,设置方式为thread.setDaemon(True),要在thread.start()之前设置,默认是false的,也就是主线程结束时,子线程依然在执行。

thread.join():在子线程完成运行之前,该子线程的父线程(一般就是主线程)将一直存在,也就是被阻塞

线程池原理
线程池基本原理: 我们把任务放进队列中去,然后开N个线程,每个线程都去队列中取一个任务,执行完了之后告诉系统说我执行完了,然后接着去队列中取下一个任务,直至队列中所有任务取空,退出线程。

上面这个例子生成一个有3个线程的线程池,每个线程都无限循环阻塞读取Queue队列的任务所有任务都只会让这3个预生成的线程来处理。

具体工作描述如下:

创建Queue.Queue()实例,然后对它填充数据或任务
生成守护线程池,把线程设置成了daemon守护线程
每个线程无限循环阻塞读取queue队列的项目item,并处理
每次完成一次工作后,使用queue.task_done()函数向任务已经完成的队列发送一个信号
主线程设置queue.join()阻塞,直到任务队列已经清空了,解除阻塞,向下执行
这个模式下有几个注意的点:

将线程池的线程设置成daemon守护进程,意味着主线程退出时,守护线程也会自动退出,如果使用默认
daemon=False的话, 非daemon的线程会阻塞主线程的退出,所以即使queue队列的任务已经完成
线程池依然阻塞无限循环等待任务,使得主线程也不会退出。

当主线程使用了queue.join()的时候,说明主线程会阻塞直到queue已经是清空的,而主线程怎么知道queue已经是清空的呢?就是通过每次线程queue.get()后并处理任务后,发送queue.task_done()信号,queue的数据就会减1,直到queue的数据是空的,queue.join()解除阻塞,向下执行。

这个模式主要是以队列queue的任务来做主导的,做完任务就退出,由于线程池是daemon的,所以主退出线程池所有线程都会退出。 有别于我们平时可能以队列主导thread.join()阻塞,这种线程完成之前阻塞主线程。看需求使用哪个join():

如果是想做完一定数量任务的队列就结束,使用queue.join(),比如爬取指定数量的网页
如果是想线程做完任务就结束,使用thread.join()

import time
import queue
import threading

queue = queue.Queue()


# 定义需要线程池执行的任务
def do_job():
    while True:
        i = queue.get()
        time.sleep(1)
        print(i, threading.current_thread())
        queue.task_done()


if __name__ == '__main__':
    # 创建包括3个线程的线程池
    time.sleep(3)
    for i in range(10):
        queue.put(i)

    for i in range(3):
        t = threading.Thread(target=do_job)
        t.daemon = True  # 设置线程daemon  主线程退出,daemon线程也会推出,即时正在运行
        t.start()

    # 模拟创建线程池3秒后塞进10个任务到队列
    queue.join()



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值