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()

 

posted @ 2021-02-17 17:14  junffzhou  阅读(185)  评论(0编辑  收藏  举报