python多线程间通信机制-event

python学习笔记之多线程间通信-event

线程间的通讯– event

  event是多线程间通信的一种简单机制,一个线程发出event信号,其他线程等待这个信号。

以一个例子来说明,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import threading
import logging
import time
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s] %(message)s')
def worker(event):
while not event.is_set():
logging.debug('in worker fun, event is set ? {0}'.format(event.is_set()))
logging.debug('event is set')
def set(event):
time.sleep(1)
event.set()
logging.debug('in set fun, event is set ? {0}'.format(event.is_set()))
if __name__ == '__main__':
event = threading.Event()
w = threading.Thread(target=worker, args=(event,), name="worker")
w.start()
s = threading.Thread(target=set, args=(event,), name="set")
s.start()

在上边的代码中定义了两个函数,并在测试代码上启用两个线程分别调用这两个函数,在调用前要初始化event对象。运行上边的代码会发现一直输出2016-08-14 20:36:49,059 DEBUG [worker] in worker fun, event is set ? False,即是调用worker函数的线程在不断执行,1秒后输出了2016-08-14 20:36:49,063 DEBUG [set] in set fun, event is set ? True,紧跟着输出2016-08-14 20:36:49,063 DEBUG [worker] event is set,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2016-08-14 20:36:49,061 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,061 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,061 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,061 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,061 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
....略.....
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,062 DEBUG [worker] in worker fun, event is set ? False
2016-08-14 20:36:49,063 DEBUG [set] in set fun, event is set ? True
2016-08-14 20:36:49,063 DEBUG [worker] event is set

为什么会这样?

因为在测试代码中启动了两个线程分别调用workerset函数,worker函数判断当event没有被set时打印类似这样日志in worker fun, event is set ? False。而set函数负责将线程内部的标志设置为true,即执行event.set()语句,它将唤醒所有线程并告知event的内部标志已为trueset函数只是sleep了1秒钟,调用woker函数的线程就执行了很多次了。此时执行worker函数的线程收到这个信号后执行到while not event.is_set()语句时,event.is_set()返回了true,所以整个while语句返回False,那while循环中的语句将被跳过,而去执行logging.debug('event is set')

  • event.wait()

  wait方法表示阻塞直到线程内部的标志为true,即有线程调用set()方法。以下边的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import threading
import logging
import time
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s] %(message)s')
def worker(event):
while not event.is_set():
event.wait()
logging.debug('in worker fun, event is set ? {0}'.format(event.is_set()))
logging.debug('event is set')
def set(event):
time.sleep(4)
event.set()
logging.debug('in set fun, event is set ? {0}'.format(event.is_set()))
if __name__ == '__main__':
event = threading.Event()
w = threading.Thread(target=worker, args=(event,), name="worker")
w.start()
s = threading.Thread(target=set, args=(event,), name="set")
s.start()

执行上边的代码时,w线程会被一直阻塞,直到4秒种之后,set函数执行到event.set(),内部标志被设置成为true,通知其他所有线程,w线程收到信号后不再阻塞。输出如下:

1
2
3
4
5
2016-08-14 21:45:26,326 DEBUG [set] in set fun, event is set ? True
2016-08-14 21:45:26,326 DEBUG [worker] in worker fun, event is set ? True
2016-08-14 21:45:26,326 DEBUG [worker] event is set
Process finished with exit code 0

wait可以设置超时时间,表示只阻塞线程一定的时间,如果收到了event.set()信号,线程退出,否则线程被阻塞,只是不是一直阻塞,而是按照设定的时间阻塞线程,如下设置wait时间,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import threading
import logging
import time
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s] %(message)s')
def worker(event):
while not event.is_set():
event.wait(timeout=1)
logging.debug('in worker fun, event is set ? {0}'.format(event.is_set()))
logging.debug('event is set')
def set(event):
time.sleep(4)
event.set()
logging.debug('in set fun, event is set ? {0}'.format(event.is_set()))
if __name__ == '__main__':
event = threading.Event()
w = threading.Thread(target=worker, args=(event,), name="worker")
w.start()
s = threading.Thread(target=set, args=(event,), name="set")
s.start()

当执行上边代码时,每隔一秒执行worker函数,当到第4秒时,event对象被setw线程收到信号就退出。

文章目录
  1. 1. 线程间的通讯– event