Python3之并发(七)---线程同步队列(queue)
queue模块实现了多生产者,多消费者队列
queue模块的常用类和异常
queue.Queue(maxsize=0) 先进先出(FIFO)的队列, maxsize: 队列的大小(即队列的元素个数),默认0,队列大小无限;如果超过maxsize,队列会加锁,添加新元素是被堵塞,直到队列中的元素小于maxsize queue.LifoQueue(maxsize=0) 后进先出(LIFO)的队列 maxsize参数同 queue.Queue 用法一样 queue.PriorityQueue(maxsize=0) 优先级队列,优先级小的元素先出,优先级通过 sorted(list(entries))[0] 的返回值决定 maxsize参数同 queue.Queue 用法一样 queue.SimpleQueue 无限FIFO队列 queue.Empty 异常 为空的queue对象调用 Queue.get() 方法引发该异常 queue.Full 异常 已满的queue对象调用 Queue.put() 方法引发该异常
队列对象方法
Queue,LifoQueue,PriorityQueue对象的方法一样,使用Queue类说明
Queue.qsize() 返回队列的元素个数 Queue.empty() 队列为空返回 True,否则返回 False Queue.full() 队列已满返回 True,否则返回 False Queue.put(item, block=True, timeout=None) 往队列里加入item,即生产元素,默认队列已满时会堵塞不引发异常 block: 队列已满时是否堵塞当前准备往队列里加入元素的线程,默认True timeout: 线程被堵塞的时长,默认None 若队列已满且block=False,会引发 queue.FULL 异常 若队列已满且block=True,在timeout时间内,队列一直处于已满状态,引发 queue.FULL 异常 Queue.put_nowait(item) 相当于Queue.put(item, block=False),队列元素已满,直接引发queue.FULL异常 Queue.get(block=True, timeout=None) 删除并返回队列里的一个item,即消费元素,默认队列已空时会堵塞不引发异常 block: 队列已空时是否堵塞当前准备往队列里取出元素的线程,默认True timeout: 线程被堵塞的时长,默认None, 若队列已空且block=False,会引发 queue.Empty 异常 若队列已空且block=True,在timeout时间内,队列一直处于空状态,引发 queue.Empty异常 Queue.get_nowait() 相当于Queue.get(block=False),队列元素为空,直接引发 queue.Empty 异常 Queue.task_done() 使用 Queue.get() 方法之后,调用该方法告诉队列当前任务已完成,队列里的item减少一个 通常配合 Queue.join() 方法使用 Queue.join() 堵塞当前线程,知道对垒中的所有任务完成 当队列的item数量为0,Queue.join() 方法取消堵塞
示例
import threading, queue from concurrent.futures import ThreadPoolExecutor #账户类 class Account: def __init__(self, account_no, balance): #账户编号和账户余额 self.account_no = account_no self.balance = balance def getBlance(self): return self.balance #提取现金方法 def draw(self, queues): draw_amount = queues.get() if self.balance >= draw_amount: print(threading.current_thread().name+'\t取钱成功!吐出钞票:'+str(draw_amount)) self.balance -= draw_amount print(threading.current_thread().name+'操作之后\t余额为:'+str(self.balance)) else: print(threading.current_thread().name+'\t取钱失败!余额不足!\t当前余额为:'+str(self.balance)) queues.task_done() #存钱方法 def deposit(self, queues): deposit_amount = queues.get() print(threading.current_thread().name+'\t存钱成功!存入钞票:'+str(deposit_amount)) self.balance += deposit_amount print(threading.current_thread().name+'操作之后\t余额为:'+str(self.balance)) queues.task_done() queues = queue.Queue(10) for item in (2000, 1000, 1000, 900): queues.put(item) acct = Account('986623', 0) with ThreadPoolExecutor(10, thread_name_prefix='Account_Thread_Pool') as pools: pools.submit(acct.draw, queues) pools.submit(acct.deposit, queues) pools.submit(acct.deposit, queues) pools.submit(acct.draw, queues) queues.join() print(threading.current_thread().name+'结束')
import queue, threading, time #产生元素函数 def producer(que,num): for i in range(num): que.put(i) print('已放入数据:'+str(i)) print(que.empty()) print(que.qsize()) time.sleep(1) #消费元素函数 def consumer(que): while not que.empty(): print('已取出数据:'+str(que.get())) time.sleep(1) else: print('队列已空,请加入元素再取出') q = queue.Queue(1) threading.Thread(target=producer, args=(q,10), name='producer').start() threading.Thread(target=consumer, args=(q,), name='consumer').start()