python3 queue多线程通信

 更新时间:2022年07月12日 16:37:14   作者:lilongsy​​​​​​​  
这篇文章主要介绍了python3 queue多线程通信,​​Queue​​ 对象已经包含了必要的锁,所以你可以通过它在多个线程间多安全地共享数据,更多相关内容需要的朋友可以参考一下下文文章内容

queue分类

python3 queue分三类:

  • 先进先出队列
  • 后进先出的栈
  • 优先级队列

他们的导入方式分别是:

from queue import Queue
from queue import LifoQueue
from queue import

具体方法见下面引用说明。

例子一、生产消费模式

Queue 对象已经包含了必要的锁,所以你可以通过它在多个线程间多安全地共享数据。 当使用队列时,协调生产者和消费者的关闭问题可能会有一些麻烦。一个通用的解决方法是在队列中放置一个特殊的值,当消费者读到这个值的时候,终止执行。

例如:

from queue import Queue
from threading import Thread
# 用来表示终止的特殊对象
_sentinel = object()
# A thread that produces data
def producer(out_q):
for i in range(10):
print("生产")
out_q.put(i)
out_q.put(_sentinel)
# A thread that consumes data
def consumer(in_q):
while True:
data = in_q.get()
if data is _sentinel:
in_q.put(_sentinel)
break
else:
print("消费", data)
# Create the shared queue and launch both threads
q = Queue()
t1 = Thread(target=consumer, args=(q,))
t2 = Thread(target=producer, args=(q,))
t1.start()
t2.start()

结果:

本例中有一个特殊的地方:消费者在读到这个特殊值之后立即又把它放回到队列中,将之传递下去。这样,所有监听这个队列的消费者线程就可以全部关闭了。 尽管队列是最常见的线程间通信机制,但是仍然可以自己通过创建自己的数据结构并添加所需的锁和同步机制来实现线程间通信。最常见的方法是使用 Condition变量来包装你的数据结构。下边这个例子演示了如何创建一个线程安全的优先级队列。

import heapq
import threading
class PriorityQueue:
def __init__(self):
self._queue = []
self._count = 0
self._cv = threading.Condition()
def put(self, item, priority):
with self._cv:
heapq.heappush(self._queue, (-priority, self._count, item))
self._count += 1
self._cv.notify()
def get(self):
with self._cv:
while len(self._queue) == 0:
self._cv.wait()
return heapq.heappop(self._queue)[-1]

例子二、task_done和join

使用队列来进行线程间通信是一个单向、不确定的过程。通常情况下,你没有办法知道接收数据的线程是什么时候接收到的数据并开始工作的。不过队列对象提供一些基本完成的特性,比如下边这个例子中的task_done()join()

from queue import Queue
from threading import Thread
class Producer(Thread):
def __init__(self, q):
super().__init__()
self.count = 5
self.q = q
def run(self):
while self.count > 0:
print("生产")
if self.count == 1:
self.count -= 1
self.q.put(2)
else:
self.count -= 1
self.q.put(1)
class Consumer(Thread):
def __init__(self, q):
super().__init__()
self.q = q
def run(self):
while True:
print("消费")
data = self.q.get()
if data == 2:
print("stop because data=", data)
# 任务完成,从队列中清除一个元素
self.q.task_done()
break
else:
print("data is good,data=", data)
# 任务完成,从队列中清除一个元素
self.q.task_done()
def main():
q = Queue()
p = Producer(q)
c = Consumer(q)
p.setDaemon(True)
c.setDaemon(True)
p.start()
c.start()
# 等待队列清空
q.join()
print("queue is complete")
if __name__ == '__main__':
main()

结果:

例子三、多线程里用queue

设置俩队列,一个是要做的任务队列todo_queue,一个是已经完成的队列done_queue
每次执行线程,先从todo_queue队列里取出一个值,然后执行完,放入done_queue队列。
如果todo_queue为空,就退出。

import logging
import logging.handlers
import threading
import queue

log_mgr = None
todo_queue = queue.Queue()
done_queue = queue.Queue()
class LogMgr:
def __init__(self, logpath):
self.LOG = logging.getLogger('log')
loghd = logging.handlers.RotatingFileHandler(logpath, "a", 0, 1)
fmt = logging.Formatter("%(asctime)s %(threadName)-10s %(message)s", "%Y-%m-%d %H:%M:%S")
loghd.setFormatter(fmt)
self.LOG.addHandler(loghd)
self.LOG.setLevel(logging.INFO)
def info(self, msg):
if self.LOG is not None:
self.LOG.info(msg)
class Worker(threading.Thread):
global log_mgr
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
while True:
try:
task = todo_queue.get(False)
if task:
log_mgr.info("HANDLE_TASK: %s" % task)
done_queue.put(1)
except queue.Empty:
break
return
def main():
global log_mgr
log_mgr = LogMgr("mylog")
for i in range(30):
todo_queue.put("data"+str(i))
workers = []
for i in range(3):
w = Worker("worker"+str(i))
workers.append(w)
for i in range(3):
workers[i].start()
for i in range(3):
workers[i].join()
total_num = done_queue.qsize()
log_mgr.info("TOTAL_HANDLE_TASK: %d" % total_num)
exit(0)
if __name__ == '__main__':
main()

输出日志文件结果:

到此这篇关于python3 queue多线程通信的文章就介绍到这了,更多相关python queue多线程通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python字符串对象实现原理详解

    Python字符串对象实现原理详解

    这篇文章主要介绍了Python字符串对象实现原理详解,在Python世界中将对象分为两种:一种是定长对象,比如整数,整数对象定义的时候就能确定它所占用的内存空间大小,另一种是变长对象,在对象定义时并不知道是多少,需要的朋友可以参考下
    2019-07-07
  • 一文带你解密Python可迭代对象的排序问题

    一文带你解密Python可迭代对象的排序问题

    这篇文章主要为大家详细介绍一下Python中可迭代对象的排序问题,文中的示例代码讲解详细,对我们深入了解Python有一定帮助,感兴趣的可以了解一下
    2022-07-07
  • Pandas进行数据编码的十种方式总结

    Pandas进行数据编码的十种方式总结

    在机器学习中,很多算法都需要我们对分类特征进行转换(编码),即根据某一列的值,新增(修改)一列。本文为大家总结了Pandas中十种数据编码的方式,需要的可以参考一下
    2022-04-04
  • pytorch逐元素比较tensor大小实例

    pytorch逐元素比较tensor大小实例

    今天小编就为大家分享一篇pytorch逐元素比较tensor大小实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • 在Python中使用defaultdict初始化字典以及应用方法

    在Python中使用defaultdict初始化字典以及应用方法

    今天小编就为大家分享一篇在Python中使用defaultdict初始化字典以及应用方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • Python批量获取基金数据的方法步骤

    Python批量获取基金数据的方法步骤

    这篇文章主要介绍了Python批量获取基金数据的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 小议Python中自定义函数的可变参数的使用及注意点

    小议Python中自定义函数的可变参数的使用及注意点

    Python函数的默认值参数只会在函数定义处被解析一次,以后再使用时这个默认值还是一样,这在与可变参数共同使用时便会产生困惑,下面就来小议Python中自定义函数的可变参数的使用及注意点
    2016-06-06
  • 深入理解python函数递归和生成器

    深入理解python函数递归和生成器

    下面小编就为大家带来一篇深入理解python函数递归和生成器。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • 详解python UDP 编程

    详解python UDP 编程

    这篇文章主要介绍了python UDP 编程的相关资料,帮助大家更好的理解和学习python,感兴趣的朋友可以了解下
    2020-08-08
  • windows下python安装paramiko模块和pycrypto模块(简单三步)

    windows下python安装paramiko模块和pycrypto模块(简单三步)

    这篇文章主要给大家介绍了通过简单的三个步骤在windows下python中安装paramiko模块和pycrypto模块的相关资料,文中安装的步骤,简单而且又易于大家理解,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-07-07

最新评论