通过Queue类实现线程同步
Queue类表示一个FIFO(先进先出)队列,即先插入队列中的数据先获取,用于多个线程之间的信息传递。创建队列的方式比较简单,可以直接通过如下构造方法实现:
Queue(maxsize=0)
以上方法中只有一个maxsize参数,该参数指定了队列的长度,默认为0,表示队列的长度没有任何限制。
Queue类中提供了一些操作队列的常见方法,这些方法的功能说明如表1所示。
表1 Queue类的常见方法
方法 | 说明 |
---|---|
qsize() | 返回队列的大小 |
empty() | 若队列为空返回True,否则返回False |
full() | 若队列已满返回True,否则返回False |
put(item, block=True, timeout=None) | 往队尾添加一个元素。该方法中共包含3个参数,item参数代表要添加的元素值;block参数代表是否阻塞队列,若设为True,队列满时会阻塞当前线程,若设为False,队列满时会抛出queue.Full异常;timeout参数代表超时时长,若timeout设为None,会无限期等待至队列中空出一个元素单元,若timeout设为正数,会阻塞等待指定时长后,抛出queue.Full异常。需要注意的是,若block参数设为False,会忽略timeout参数 |
put_nowait(item) | 立即向队列中存入一个元素,相当于put(item, False) |
get(block=True, timeout=None) | 移除并返回队头的第一个元素。该方法中共包含2个参数,block参数代表是否阻塞队列,若设为True,队列空时会阻塞当前线程,若设为False,队列空时会抛出queue.Empty异常;timeout参数代表超时时长,若timeout设为None,会无限期等待至队列中插入一个元素,若timeout设为正数,会阻塞等待指定时长后,抛出queue.Empty异常。 |
get_nowait() | 立即从队列中取出一个元素,相当于get(False) |
为了能够让大家更好地理解,下面通过一个示例来演示如何让主线程和多个子线程协调合作,主线程往队列中插入完数据之后,它等子线程取出所有的数据之后结束执行,具体代码如下:
import threading
from queue import Queue
from threading import Thread, Lock
import time
class MyThread (Thread):
def __init__(self, threadID, name, q):
super().__init__()
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print(self.name + "开始 ")
process_data(self.name, self.q)
print(self.name + "结束 ")
def process_data(threadName, q):
while not exit_flag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print("%s 取出元素 %s" % (threadName, data))
else:
queueLock.release()
time.sleep(1)
exit_flag = 0 # 线程退出标记
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = Lock()
workQueue = Queue(10)
threads = []
threadID = 1
# 创建新线程
for tName in threadList:
thread = MyThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1
# 填充队列
queueLock.acquire()
for word in nameList:
workQueue.put(word)
print("%s 存入元素 %s" % (threading.currentThread().name, word))
queueLock.release()
# 等待队列清空
while not workQueue.empty():
pass
# 通知线程是时候退出
exit_flag = 1
# 等待所有线程完成
for t in threads:
t.join()
print("主线程结束")
运行代码,结果如下所示:
Thread-1开始
Thread-2开始
Thread-3开始
MainThread 存入元素 One
MainThread 存入元素 Two
MainThread 存入元素 Three
MainThread 存入元素 Four
MainThread 存入元素 Five
Thread-3 取出元素 One
Thread-1 取出元素 Two
Thread-2 取出元素 Three
Thread-3 取出元素 Four
Thread-2 取出元素 Five
Thread-2结束
Thread-3结束
Thread-1结束
主线程结束