Python并发编程之消息队列补充及如何创建线程池(六)
大家好,并发编程 进入第六篇。
在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用。昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知识点,也并不是无关紧要的,所以在今天的章节里,我要先对Queue先做一些补充以防大家对消息队列有一些知识盲区。
再次提醒:
本系列所有的代码均在Python3下编写,也建议大家尽快投入到Python3的怀抱中来。
本文目录
- 消息队列的先进先出
- 创建多线程的两种方式
. 消息队列的先进先出
首先,要告诉大家的事,消息队列可不是只有queue.Queue这一个类,除它之外,还有queue.LifoQueue和queue.PriorityQueue这两个类。
从名字上,对于他们之间的区别,你大概也能猜到一二吧。
queue.Queue:先进先出队列queue.LifoQueue:后进先出队列queue.PriorityQueue:优先级队列
先来看看,我们的老朋友,queue.Queue。
所谓的先进先出(FIFO,First in First Out),就是先进入队列的消息,将优先被消费。
这和我们日常排队买菜是一样的,先排队的人肯定是先买到菜。
用代码来说明一下
import queue
q = queue.Queue()
for i in range(5):
q.put(i)
while not q.empty():
print q.get()
看看输出,符合我们先进先出的预期。存入队列的顺序是01234,被消费的顺序也是01234。
0
1
2
3
4
再来看看Queue.LifoQueue,后进先出,就是后进入消息队列的,将优先被消费。
这和我们羽毛球筒是一样的,最后放进羽毛球筒的球,会被第一个取出使用。
用代码来看下
import queue
q = queue.LifoQueue()
for i in range(5):
q.put(i)
while not q.empty():
print q.get()
来看看输出,符合我们后进后出的预期。存入队列的顺序是01234,被消费的顺序也是43210。
4
3
2
1
0
最后来看看Queue.PriorityQueue,优先级队列。
这和我们日常生活中的会员机制有些类似,办了金卡的人比银卡的服务优先,办了银卡的人比不办卡的人服务优先。
来用代码看一下
from queue import PriorityQueue
# 重新定义一个类,继承自PriorityQueue
class MyPriorityQueue(PriorityQueue):
def __init__(self):
PriorityQueue.__init__(self)
self.counter = 0
def put(self, item, priority):
PriorityQueue.put(self, (priority, self.counter, item))
self.counter += 1
def get(self, *args, **kwargs):
_, _, item = PriorityQueue.get(self, *args, **kwargs)
return item
queue = MyPriorityQueue()
queue.put('item2', 2)
queue.put('item5', 5)
queue.put('item3', 3)
queue.put('item4', 4)
queue.put('item1', 1)
while True:
print(queue.get())
来看看输出,符合我们的预期。我们存入入队列的顺序是25341,对应的优先级也是25341,可是被消费的顺序丝毫不受传入顺序的影响,而是根据指定的优先级来消费。
item1
item2
item3
item4
item5
. 创建多线程的两种方式
在使用多线程处理任务时也不是线程越多越好,由于在切换线程的时候,需要切换上下文环境,依然会造成cpu的大量开销。为解决这个问题,线程池的概念被提出来了。预先创建好一个较为优化的数量的线程,让过来的任务立刻能够使用,就形成了线程池。
在Python3中,创建线程池是通过concurrent.futures函数库中的ThreadPoolExecutor类来实现的。
import time
import threading
from concurrent.futures import ThreadPoolExecutor
def target():
for i in range(5):
print('running thread-{}:{}'.format(threading.get_ident(), i))
time.sleep(1)
#: 生成线程池最大线程为5个
pool = ThreadPoolExecutor(5)
for i in range(100):
pool.submit(target) # 往线程中提交,并运行
从结果来看,前面设置线程池最大线程数5个,有生效。
running thread-11308:0
running thread-12504:0
running thread-5656:0
running thread-12640:0
running thread-7948:0
running thread-11308:1
running thread-5656:1
running thread-7948:1
running thread-12640:1
running thread-12504:1
...
...
除了使用上述第三方模块的方法之外,我们还可以自己结合前面所学的消息队列来自定义线程池。
这里我们就使用queue来实现一个上面同样效果的例子,大家感受一下。
import time
import threading
from queue import Queue
def target(q):
while True:
msg = q.get()
for i in range(5):
print('running thread-{}:{}'.format(threading.get_ident(), i))
time.sleep(1)
def pool(workers,queue):
for n in range(workers):
t = threading.Thread(target=target, args=(queue,))
t.daemon = True
t.start()
queue = Queue()
# 创建一个线程池:并设置线程数为5
pool(5, queue)
for i in range(100):
queue.put("start")
# 消息都被消费才能结束
queue.join()
输出是和上面是完全一样的效果
running thread-11308:0
running thread-12504:0
running thread-5656:0
running thread-12640:0
running thread-7948:0
running thread-11308:1
running thread-5656:1
running thread-7948:1
running thread-12640:1
running thread-12504:1
...
...
构建线程池的方法,是可以很灵活的,大家有举可以自己多研究。但是建议只要掌握一种自己熟悉的,能快速上手的就好了。
好了,今天的内容就是这些了。
Python并发编程之消息队列补充及如何创建线程池(六)的更多相关文章
- Python并发编程-RabbitMQ消息队列
RabbitMQ队列 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列 ...
- python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02
目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...
- JUC 并发编程--09, 阻塞队列: DelayQueue, PriorityBlockingQueue ,SynchronousQueue, 定时任务线程池: ScheduledThreadPoolExecutor
先看DelayQueue 这个是用优先级队列实现的无界限的延迟队列,直接上代码: /** * 这个是 {@link DelayQueue} 延时队列 的验证使用类 */ class MyDelayed ...
- Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁
Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...
- 并发编程中死锁、递归锁、进程/线程池、协程TCP服务器并发等知识点
1.死锁 定义; 类似两个人分别被囚禁在两间房子里,A手上拿着的是B囚禁房间的钥匙,而B拿着A的钥匙,两个人都没法出去,没法给对方开锁,进而造成死锁现象.具体例子代码如下: # -*-coding:u ...
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- Python 3 并发编程多进程之队列(推荐使用)
Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...
- python 并发编程 多进程 队列目录
python 并发编程 多进程 队列 python 并发编程 多进程 生产者消费者模型介绍 python 并发编程 多进程 生产者消费者模型总结 python 并发编程 多进程 JoinableQue ...
- Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信
Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...
随机推荐
- wait event & wake up
在linux驱动中一个常用的场景, 驱动需要等待中断的响应, 才得以执行后续的代码,达到一个原子操作的目的 /* 静态申请队列 */ static DECLARE_WAIT_QUEUE_HEAD(s_ ...
- web 基础设置
1.设置代码格式为UTF-8 2.运行jsp文档 3.设置自己喜欢的浏览器运行,设置为默认的 找到自己的浏览器位置 点ok Name是名字的意思 为这个浏览器娶一个名字 是什么浏览器就写什么名字 4. ...
- DIV滚动条滚动到指定位置(jquery的position()与offset()方法区别小记)
相对浏览器,将指定div滚到到指定位置,其用法如下 $("html,body").animate({scrollTop: $(obj).offset().top},speed); ...
- 用 PHP文件引入css样式
html: <link rel="stylesheet" type="text/css" href="http://www.mysite.com ...
- Hadoop集群搭建-HA高可用(手动切换模式)(四)
步骤和集群规划 1)保存完全分布式模式配置 2)在full配置的基础上修改为高可用HA 3)第一次启动HA 4)常规启动HA 5)运行wordcount 集群规划: centos虚拟机:node-00 ...
- day11函数(形参实参)
形参与实参 def fn(形参们): pass # 形参:定义函数,在括号内声明的变量名,用来结束外界传来的值# 实参:调用函数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合 # 注: ...
- Foxmail6.5 ERR LOGIN FAIL 重新输入口令
这几天 Foxmail 6.5 收邮件不正常,一直报告ERR LOGIN FAIL,要求重新输入口令. 但输入正确的口令也无法收邮件. 反复折腾,最后发现如下设置即可: 邮箱账户设置 --> 邮 ...
- Tomcat优化详解
1 概述 本文档主要介绍了Tomcat的性能调优的原理和方法.可作为公司技术人员为客户Tomcat系统调优的技术指南,也可以提供给客户的技术人员作为他们性能调优的指导 ...
- Java面试大纲-java面试该做哪些准备,java开发达到这样的水平可以涨工资
Java培训结束,面临的就是毕业找工作.在找工作时,就要针对性地做充分的面试准备.准备不充分的面试,完全是浪费时间,更是对自己的不负责. 上海尚学堂Java培训整理出Java面试大纲,其中大部分都是面 ...
- storm集群架构
一.storm何许人也? Storm 是Twitter的一个开源框架.Storm一个分布式的.容错的实时计算系统,它被托管在GitHub上,遵循 Eclipse Public License 1.0. ...