一.Event
如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时候就可以用threading为我们提供的Event对象,Event对象主要有一下几个方法:
isSet():返回event的状态值;
wait():如果 event==False 将阻塞当前线程;
set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
clear():恢复event的状态值为False。
有如下需求:获取当前时间的秒数的个位数,如果小于5,设置子线程阻塞,如果大于5则设置子进程非阻塞。代码如下:
from threading import Event, Thread
import time
from datetime import datetime
def func(e):
print('子线程:开始运行……')
while True:
print('子线程:现在事件秒数是{}'.format(datetime.now().second))
e.wait() # 阻塞等待信号 这里插入了一个Flag 默认为 False
time.sleep(1)
e = Event()
p = Thread(target=func, args=(e,))
p.daemon=True
p.start()
for i in range(10):
s = int(str(datetime.now().second)[-1])#获取当前秒数的个位数
if s < 5:
print('子线程线入阻塞状态')
e.clear() # 使插入的flag为False 线程线入阻塞状态
else:
print('子线程取消阻塞状态')
e.set() # 线程线入非阻塞状态
time.sleep(1)
e.set()
print("主线程运行结束……")
>>>
输出结果:
子线程:开始运行……
子线程:现在事件秒数是43
子线程线入阻塞状态
子线程线入阻塞状态
子线程取消阻塞状态
子线程取消阻塞状态
子线程:现在事件秒数是46
子线程取消阻塞状态
子线程:现在事件秒数是47
子线程取消阻塞状态
子线程:现在事件秒数是48
子线程取消阻塞状态
子线程:现在事件秒数是49
子线程线入阻塞状态
子线程:现在事件秒数是50
子线程线入阻塞状态
子线程线入阻塞状态
主线程运行结束……
二.queue (推荐使用)
python中Queue模块提供了队列都实现了锁原语,是线程安全的,能够在多线程中直接使用。Queue中的队列包括以下三种:
1)FIFO(先进先出)队列, 第一加入队列的任务, 被第一个取出;
2)LIFO(后进先出)队列,最后加入队列的任务, 被第一个取出;
3)PriorityQueue(优先级)队列, 保持队列数据有序, 最小值被先取出。
Queue模块中的常用方法如下:
qsize() 返回队列的规模
empty() 如果队列为空,返回True,否则False
full() 如果队列满了,返回True,否则False
get([block[, timeout]])获取队列,timeout等待时间
get_nowait() 相当get(False)
put(item) 写入队列,timeout等待时间,如果队列已满再调用该方法会阻塞线程
put_nowait(item) 相当put(item, False)
task_done() 在完成一项工作之后,task_done()函数向任务已经完成的队列发送一个信号
join() 实际上意味着等到队列为空,再执行别的操作。
import queue
import threading
def fun():
while True:
try:
data = q.get(block = True, timeout = 1) #不设置阻塞的话会一直去尝试获取资源
except queue.Empty:
print(' {}结束……'.format(threading.current_thread().name))
break
print(' {}取得数据:{}'.format(threading.current_thread().name , data))
q.task_done()
print(' {}结束……'.format(threading.current_thread().name))
print("主线程开始运行……")
q = queue.Queue(5)
#往队列里面放5个数
for i in range(5):
q.put(i)
for i in range(0, 3):
t = threading.Thread(target=fun , name='线程'+str(i))
t.start()
q.join() #等待所有的队列资源都用完
print("主线程结束运行……")
》》》
输出结果:
主线程开始运行……
线程0取得数据:0
线程0结束……
线程0取得数据:1
线程0结束……
线程1取得数据:2
线程0取得数据:3
线程0结束……
线程0取得数据:4
线程0结束……
线程1结束……
主线程结束运行……
线程1结束……
线程2结束……
线程0结束……
参考: