二十三、Python队列实现多线程(下篇)
「@Author: Runsen」
在Python中 , 主要采用队列和线程的方法来实现多线程 。
队列队列(queue) , 是先进先出(FIFO, First-In-First-Out)的线性表 , 在具体应用中通常用链表或者数组来实现 , 队列只允许在后端(称为rear)进行插入操作 , 在前端(称为front)进行删除操作 , 队列的操作方式和堆栈类似 , 唯一的区别在于队列只允许新数据在后端进行添加 。
文章插图
在Python中队列可以通过内置模块queue导入 , 具体导入方法:from queue import Queue 。
queuequeue模块提供了适合多线程编程的先进先出的数据结构 , 可以用来在生产者和消费者线程之间安全的传递消息或者数据;锁是调用方处理 , 因此多线程可以安全、方便的使用同一队列实现 。
文章插图
常用属性和方法:
Queue类实现了一个基本的先进先出容器 。 使用put方法将元素增加到序列的一端 , 使用get方法从另一端删除 , 具体代码如下 。
import queueq = queue.Queue()#添加元素for i in range(5):q.put(i)#删除元素while not q.empty():print(q.get())
运行上面的程序 , 你将会看到下面的输出:
01234
生产者/消费者模式我们经常会遇到这样的一个问题 , 这里有成千上万条数据 , 每次需要取出其中的一条数据进行处理 , 那么引入多线程该怎么进行任务分配?
我们可以将数据进行分割然后交给多个线程去跑 , 因为线程间数据的共享的问题 。
它包含两类进程:一种只是用来生产数据,例外一种只是用来消费数据.为了串联他们,通常会采用共享的数据区域,就像一个仓库.生产者产生的数据都放入仓库中并不需要关注消费者的行为,消费者只需要从共享仓库中获取数据,并不需要关心生产者的行为.
# -*- coding:utf-8 -*-# time :2019/4/23 10:13# Author: Maoliimport threadingimport timeimport randomMONEY = 0gLock = threading.Lock()def Procuder():while True:global MONEYrandom_money = random.randint(10,100)gLock.acquire() #加锁MONEY += random_moneygLock.release() #释放锁print ('生产者%s-生产了%d' % (threading.current_thread,random_money))time.sleep(0.5)def Customer():while True:global MONEYrandom_money = random.randint(10,100)if MONEY > random_money:print ('消费者%s-消费了:%d' % (threading.current_thread,random_money))gLock.acquire()MONEY -= random_moneygLock.release()else:print ('需要消费的钱为:%d , 余额为:%d , ' % (random_money,MONEY))time.sleep(0.5)def p_c_test():# 执行3个线程 , 来当作生产者for x in range(3):th = threading.Thread(target=Procuder)th.start()# 执行3个线程 , 来当作消费者for x in range(3):th = threading.Thread(target=Customer)th.start()if __name__ == "__main__":p_c_test()
运行截图如下:
文章插图
队列实现多线程在这里我们可以使用队列与线程相结合的方式进行任务分配 。 在生产消费者模式当中用到的是阻塞型queue 。 在Python当中 , 我们最常用的queue就是一个支持多线程场景的阻塞队列
队列线程的思想: 首先创建一个全局共享的队列 , 队列中只存在有限个元素 , 并将所有的数据逐条加入到队列中 , 并调用队列的join函数进行等待 。 之后便可以开启若干线程 , 线程的任务就是不断的从队列中取数据进行处理就可以了 。
# -*- coding:utf-8 -*-# time :2019/4/23 10:35# Author: Maoliimport threadingimport timeimport queue# 下面来通过多线程来处理Queue里面的任务:def work(q):while True:if q.empty():returnelse:t = q.get()print("当前线程sleep {} 秒".format(t))time.sleep(t)def main():q = queue.Queue()for i in range(5):q.put(i)# 往队列里生成消息thread_num = 5threads = []for i in range(thread_num):t = threading.Thread(target=work, args=(q,))# args需要输出的是一个元组 , 如果只有一个参数 , 后面加 , 表示元组 , 否则会报错threads.append(t)# 创建5个线程for i in range(thread_num):threads[i].start()for i in range(thread_num):threads[i].join()if __name__ == "__main__":start = time.time()main()print('耗时:', time.time() - start)
运行上面的程序 , 你将会看到下面的输出:
当前线程sleep 0 秒当前线程sleep 1 秒当前线程sleep 2 秒当前线程sleep 3 秒当前线程sleep 4 秒耗时: 4.002955436706543
今天也学到了很多东西呢 , 明天有什么新知识呢?真期待鸭~如果喜欢文章可以关注我哦~
?
本文已收录 GitHub , 传送门~[1], 里面更有大厂面试完整考点 , 欢迎 Star 。
- 空调|让格力、海尔都担忧,中国取暖“新潮物”强势来袭,空调将成闲置品?
- 占营收|华为值多少钱
- 俄罗斯手机市场|被三星、小米击败,华为手机在俄罗斯排名跌至第三!
- 页面|如何简单、快速制作流程图?上班族的画图技巧get
- 操盘|中兴统一操盘中兴、努比亚、红魔三大品牌
- 印度|拒绝华为后,印度、英国斥资数十亿求助日本
- 华为|台积电、高通、华为、小米接连宣布!美科技界炸锅:怎么会这样!
- 拍照|iPhone12还没捂热13就曝光了,屏幕、信号、拍照均有升级!
- 路由器|家里无线网经常断网、网速慢怎么办?教你几个小窍门,轻松解决
- 一图看懂!数字日照、新型智慧城市这样建(上篇)|政策解读 | 新型