【QT八股文】系列之篇章3 | QT的多线程
前言
- 第一篇章主要是基础定义及QT中重要的事件机制
笔记链接:【QT八股文】系列之篇章1 | QT的基础知识及事件/机制 - 第二篇章主要是QT的信号与槽以及通讯流程
笔记链接:【QT八股文】系列之篇章2 | QT的信号与槽及通讯流程
这里我们主要件点更实际的,也就是多线程以及QThread与QObject
因为介绍到信号与槽,所以笔者我会讲通讯流程提前在前面来介绍
原创文章,未经同意请勿转载
4. 多线程
为什么需要使用线程池
- 减少系统开销:频繁创建/销毁线程的开销大,影响处理效率。而在线程池缓存线程可用已有的闲置线程来执行新任务,避免了创建/销毁带来的系统开销。
- 避免阻塞问题:线程并发数量过多,抢占系统资源从而导致阻塞。线程能共享系统资源,如果同时执行的线程过多,就有可能导致系统资源不足而产生阻塞的情况。
- 管理和控制线程:运用线程池可以进行多线程的调度,有利于延迟执行,优先级执行和定时循环执行策略
线程池的基础知识
这里必须要知道线程池实现主要依靠两个部分,一个是任务队列,另外一个是线程的管理控制中心
很明显。任务队列的数据结构就是队列,先进先出,用Queue模块实现,那先了解一下Queue:
- Queue的常用方法
- Queue.qsize():返回queue的大小。
- Queue.empty():判断队列是否为空,通常不太靠谱。
- Queue.full():判断是否满了。
- Queue.put(item, block=True, timeout=None): 往队列里放数据。
- Queue.put_nowait(item):往队列里存放元素,不等待
- Queue.get(item, block=True, timeout=None): 从队列里取数据。
- Queue.get_nowait(item):从队列里取元素,不等待
- Queue.task_done():表示队列中某个元素是否的使用情况,使用结束会发送信息。
- Queue.join():一直阻塞直到队列中的所有元素都执行完毕。
python中创建线程池的方法
这里必须要知道线程池实现主要依靠两个部分,一个是任务队列,另外一个是线程的管理控制中心
- 使用threading库+队列Queue来实现线程池
- 使用threadpool模块,这是个python的第三方模块,支持python2和python3
- 使用concurrent.futures模块,这个模块是python3中自带的模块,python2.7以上版本也可以安装使用
使用threading库+队列Queue来实现线程池
1、创建一个 Queue.Queue() 的实例,然后使用数据对它进行填充。
2、将经过填充数据的实例传递给线程类,后者是通过继承threading.Thread 的方式创建的。
3、生成守护线程池。
4、每次从队列中取出一个项目,并使用该线程中的数据和 run 方法以执行相应的工作。
5、在完成这项工作之后,使用 queue.task_done() 函数向任务已经完成的队列发送一个信号。
6、对队列执行 join 操作,实际上意味着等到队列为空,再退出主程序。
在使用这个模式时需要注意一点:通过将守护线程设置为 true,程序运行完自动退出。好处是在退出之前,可以对队列执行 join 操作、或者等到队列为空。
-
代码
import Queue import threading import time queue = Queue.Queue() class ThreadNum(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue def run(self): while True: #消费者端,从队列中获取num num = self.queue.get() print("Retrieved", num) time.sleep(1) #在完成这项工作之后,使用 queue.task_done() 函数向任务已 经完成的队列发送一个信号 self.queue.task_done() print("Consumer Finished") def main(): #产生一个 threads pool, 并把消息传递给thread函数进行处理,这 里开启10个并发 for i