Python 多线程 -- 事件通知 threading.Event

有时候,我们线程 A 和 B 运行中,需要等待某个条件 (某件事情发生),才能继续运行下面的代码。事件还没发生前,线程阻塞住,直到事件的发生。 
Python 中 threading.Event 就可以实现线程间的事件通知。

threading.Event

  • 等待事件者,调用 wait,等待事件
  • 通知事件者,调用 set,通知事件
  • wait 可以接受到参数,等待多少秒,默认是一直阻塞等待下去

简单示例

import threading
import time,random

def say(e):
    time.sleep(random.random())
    print '准备说话中。。。。'
    e.wait()
    time.sleep(random.random())
    print('%s->可以开始说话了' % (threading.currentThread().name))

e = threading.Event()
t1 = threading.Thread(target=say, args=(e,), name='线程1')
t2 = threading.Thread(target=say, args=(e,), name='线程2')
t1.start()
t2.start()

time.sleep(10)
e.set()

结果:

准备说话中。。。。
准备说话中。。。。
线程1->可以开始说话了
线程2->可以开始说话了

示例二

创建个继承 threading.Thread 的类 Player。

Player 类 run 方法中,要等待上一个通知操作, 操作了后,通知下一家操作。
e_pre.wait()[等待上一家通知] –> 操作 –> e_self.set()[通知下一家操作]。 每个操作三次。

import threading,time

class Player(threading.Thread):
    def __init__(self, name , e_pre, e_self):
        threading.Thread.__init__(self)
        self.name = name
        self.e_pre = e_pre
        self.e_self = e_self
        self.count = 0

    def run(self):
        while self.count < 3:
            self.count += 1
            time.sleep(2.1)
            self.e_pre.wait()

            print('%s 第%d次操作===>' % (self.name, self.count))
            time.sleep(1)
            self.e_self.set()
        time.sleep(0.1)
        print('%s Done!' % self.name)

创建 3 个 Player 实例,a、b、c;
3 个 threading.Event 实例,a_event, b_event, c_event。
操作顺序: a -> b -> c。
通知顺序:

c_event.set(), 通知 a 可以操作了。a_event.set() 就可以通知 b 操作了,b_evnet.set(), 通知 c 可以操作了。

# a,b,c用户,分别对于三个event,负责通知下一个用户操作
a_event = threading.Event()
b_event = threading.Event()
c_event = threading.Event()
# 操作顺序: a -> b -> c
# 通知操作: c_event -> a ; a_event -> b; b_event ->c

a = Player('A', c_event, a_event)
b = Player('B', a_event, b_event)
c = Player('C', b_event, c_event)

for i in [a, b, c]:
    i.start()

# 延时要配置好,要不,输出顺序会乱
time.sleep(3)
# 最开始是由a出牌
# b_event.set()
c_event.set()

for i in [a, b, c]:
    i.join()

print('-'*15)

输出结果:

A 第1次操作===>
B 第1次操作===>
C 第1次操作===>
A 第2次操作===>
B 第2次操作===>
C 第2次操作===>
A 第3次操作===>
B 第3次操作===>
A Done!
C 第3次操作===>
B Done!
C Done!
---------------

注意: time.sleep 参数的配置要合理 (否则输出结果顺序不对),本示例只是简单演示。