python多线程编程和学习(Queue模块)

学习多线程可能我们会遇到生产者和消费者的问题,操作系统的经典问题在python怎么实现,代码如下(有疑问可以看注释)后面简单介绍一下这个Queue的用法
线程安全问题?
这个模块是线程安全的,不存在同时操作一个数据的问题
Queue 模块提供一个适用于多线程编程的先进先出(first-in,first-out,FIFO)数据结构,可以用来在生产者消费者线程之间安全地传递消息或其他数据。它会为调用者处理锁定,使用多个线程可以安全地处理同一个 Queue 实例。Queue 的大小(其中包含的元素个数)可能要受限,以限制内存使用或处理。

#python多线程编程和学习(Queue模块)

import queue
import threading
import time
import random



def read(queue,loops):
    # loops相当于读取多少个数据 
    for i in range(loops):
        time.sleep(random.randint(2,5))
        # 参数如果不是0就会阻塞到队列有对象为止
        item=queue.get(1)
        print("reader one data from queue(size): ",queue.qsize())

def write(queue,loops):
    # loops相当于写入多少个数据
    for i in range(loops):
        time.sleep(random.randint(1, 3))
        item='test'
        # queue后面参数如果不是0就会阻塞直到有空间写入
        queue.put(item,'1')
        print("Put one data to queue(size): ",queue.qsize())

if __name__ == '__main__':
    q=queue.Queue(maxsize=10)
    threads=[]
    th1=threading.Thread(target=write,args=(q,10))
    threads.append(th1)
    th2=threading.Thread(target=read,args=(q,5))
    threads.append(th2)
    for th in threads:
        th.setDaemon(True)
        th.start()
    for th in threads:
        # 设置了setDaemon
        # 原来是setDaemon,主线程启动两个子线程后
        # 做事后,主线程就不管子线程是否运行完毕,直接往下运行,然后就结束了
        # 去掉join(),会发生什么,大家可以试一下
        # join()是让主线程等待子线程运行完
        th.join()
运行:
Put one data to queue(size):  1
reader one data from queue(size):  0
Put one data to queue(size):  1
Put one data to queue(size):  2
reader one data from queue(size):  1
Put one data to queue(size):  2
Put one data to queue(size):  3
reader one data from queue(size):  2
Put one data to queue(size):  3
reader one data from queue(size):  2
Put one data to queue(size):  3
Put one data to queue(size):  4
Put one data to queue(size):  5
reader one data from queue(size):  4
Put one data to queue(size):  5

Queue的三种构造方法:
1、class Queue.Queue(maxsize) FIFO
2、class Queue.LifoQueue(maxsize) LIFO
3、class Queue.PriorityQueue(maxsize) 优先级队列
(阻塞问题可以看代码注释)

常用方法:
Queue.qsize()
Queue.empty()
Queue.full()
Queue.put(item, block=True, timeout=None)
放item到队列中。如果block是True,且timeout是None,该方法将一直等待直到有队列有空余空间。如果timeout是一个正整数,该方法则最多阻塞timeout秒并抛出Full异常。如果block是False并且队列满,则直接抛出Full异常(这时timeout将被忽略)。

Queue.get(block=True, timeout=None)
从队列中移除被返回一个条目。如果block是True并且timeout是None,该方法将阻塞直到队列中有条目可用。如果timeout是正整数,该方法将最多阻塞timeout秒并抛出Empty异常。如果block是False并且队列为空,则直接抛出Empty异常(这时timeout将被忽略)。

Queue.task_done()
表示一个先前的队列中的任务完成了。被队列消费者线程使用。对于每个get()获取到的任务,接下来的task_done()的调用告诉队列该任务的处理已经完成。
如果join()调用正在阻塞,当队列中所有的条目被处理后它将恢复执行(意味着task_done()调用将被放入队列中的每个条目接收到)。
如果调用次数超过了队列中放置的条目数目,将抛出ValueError异常。

Queue.join()
阻塞直到队列中所有条目都被获取并处理。
当一个条目被增加到队列时,未完成任务的计数将增加。当一个消费者线程调用task_done()时,未完成任务的计数将减少。当未完成任务的计数减少到0时,join()解锁。

你可能感兴趣的:(python学习)