Python的Queue模块提供一种适用于多线程编程的FIFO实现。它可用于在生产者(producer)和消费者(consumer)之间线程安全(thread-safe)地传递消息或其它数据,因此多个线程可以共用同一个Queue实例。Queue的大小(元素的个数)可用来限制内存的使用。

Basic FIFO Queue

Queue类实现了一个基本的先进先出(FIFO)容器,使用put()将元素添加到序列尾端,get()从队列尾部移除元素。

LIFO Queue

与标准FIFO实现Queue不同的是,LifoQueue使用后进先出序(会关联一个栈数据结构)。

Priority Queue(优先队列)

除了按元素入列顺序外,有时需要根据队列中元素的特性来决定元素的处理顺序。例如,财务部门的打印任务可能比码农的代码打印任务优先级更高。PriorityQueue依据队列中内容的排序顺序(sort order)来决定那个元素将被检索。

Using Queues with Threads

queue介绍

queue是python中的标准库,俗称队列,可以直接import 引用,在python2.x中,模块名为Queue

在python中,多个线程之间的数据是共享的,多个线程进行数据交换的时候,不能够保证数据的安全性和一致性,所以当多个线程需要进行数据交换的时候,队列就出现了,队列可以完美解决线程间的数据交换,保证线程间数据的安全性和一致性

queue模块有三种队列及构造函数:

Python queue模块的FIFO队列先进先出。

class queue.Queue(maxsize)

LIFO类似于堆,即先进后出。

class queue.LifoQueue(maxsize)

还有一种是优先级队列级别越低越先出来。

class queue.PriorityQueue(maxsize)

queue模块中的常用方法:

queue.qsize() 返回队列的大小
queue.empty() 如果队列为空,返回True,反之False
queue.full() 如果队列满了,返回True,反之False
queue.full 与 maxsize 大小对应
queue.get([block[, timeout]])获取队列,timeout等待时间
queue.get_nowait() 相当queue.get(False)
queue.put(item) 写入队列,timeout等待时间
queue.put_nowait(item) 相当queue.put(item, False)
queue.task_done() 在完成一项工作之后,queue.task_done()函数向任务已经完成的队列发送一个信号
queue.join() 实际上意味着等到队列为空,再执行别的操作

代码例子:

#coding: utf-8
from queue importQueue#Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递
deftest_queue():
q=Queue(10)for i in range(5):
q.put(i)while notq.empty():print(q.get())deftest_LifoQueue():importqueue#queue.LifoQueue() #后进先出->堆栈
q = queue.LifoQueue(3)
q.put(1)
q.put(2)
q.put(3)print(q.get())print(q.get())print(q.get())deftest_PriorityQueue():importqueue#queue.PriorityQueue() #优先级
q = queue.PriorityQueue(3) #优先级,优先级用数字表示,数字越小优先级越高
q.put((10, 'a'))
q.put((-1, 'b'))
q.put((100, 'c'))print(q.get())print(q.get())print(q.get())#Python queue队列,实现并发,在网站多线程推荐最后也一个例子,比这货简单,但是不够规范
from queue import Queue #Queue在3.x中改成了queue
importrandomimportthreadingimporttimefrom threading importThreadclassProducer(threading.Thread):"""Producer thread 制作线程"""
def __init__(self, t_name, queue): #传入线程名、实例化队列
threading.Thread.__init__(self, name=t_name) #t_name即是threadName
self.data =queue"""

run方法 和start方法:

它们都是从Thread继承而来的,run()方法将在线程开启后执行,

可以把相关的逻辑写到run方法中(通常把run方法称为活动[Activity]);

start()方法用于启动线程。"""
defrun(self):for i in range(5): #生成0-4五条队列
print("%s: %s is producing %d to the queue!" % (time.ctime(), self.getName(), i)) #当前时间t生成编号d并加入队列
self.data.put(i) #写入队列编号
time.sleep(random.randrange(10) / 5) #随机休息一会
print("%s: %s producing finished!" % (time.ctime(), self.getName)) #编号d队列完成制作
classConsumer(threading.Thread):"""Consumer thread 消费线程,感觉来源于COOKBOOK"""
def __init__(self, t_name, queue):
threading.Thread.__init__(self, name=t_name)
self.data=queuedefrun(self):for i in range(5):
val=self.data.get()print("%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val)) #编号d队列已经被消费
time.sleep(random.randrange(10))print("%s: %s consuming finished!" % (time.ctime(), self.getName())) #编号d队列完成消费
defmain():"""Main thread 主线程"""queue= Queue() #队列实例化
producer = Producer('Pro.', queue) #调用对象,并传如参数线程名、实例化队列
consumer = Consumer('Con.', queue) #同上,在制造的同时进行消费
producer.start() #开始制造
consumer.start() #开始消费
"""join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。"""producer.join()
consumer.join()print('All threads terminate!')if __name__=="__main__":
test_queue()print("=====后进先出=====")
test_LifoQueue()print("=====优先级======")
test_PriorityQueue()
main()

线程模块

- 多线程主要的内容:直接进行多线程操作,线程同步,带队列的多线程;

Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。

_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

threading.currentThread(): 返回当前的线程变量。

threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

run(): 用以表示线程活动的方法。

start():启动线程活动。

join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。

isAlive(): 返回线程是否活动的。

getName(): 返回线程名。

setName(): 设置线程名。

#queue 多线程各个线程的运算的值放到一个队列中,到主线程的时候再拿出来,以此来代替#return的功能,因为在线程是不能返回一个值的

importtimeimportthreadingfrom Queue importQueuedefjob(l,q):
q.put([i**2 for i inl])defmultithreading(data):
q=Queue()
threads=[]for i in xrange(4):
t= threading.Thread(target = job,args =(data[i],q))
t.start()
threads.append(t)for thread inthreads:
thread.join()
results=[]for _ in range(4):
results.append(q.get())printresultsif __name__ == "__main__":
data= [[1,2,3],[4,5,6],[3,4,3],[5,5,5]]
multithreading(data)
[[1, 4, 9], [16, 25, 36], [9, 16, 9], [25, 25, 25]]