python多线程中setDaemon与join的问题

最近因为需要,看了一下python多线程,主要的需求点在是否可以接受用户的中断而退出。

在python中,join, setDaemon是用来对线程做处理的。但是这两个函数实现的功能基本上是相反的。

我们写一个简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import re
from threading import Thread
import time
class TestDaemon(Thread):
"""docstring for TestDaemon"""
def __init__(self, arg):
Thread.__init__(self)
self.arg = arg
def run(self):
while True:
print "Threading number : {}".format(self.arg)
time.sleep(0.01)

在这个例子中,如果我们用join函数来实现其main函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def main():
threads = []
for i in range(5):
t = TestDaemon(i)
threads.append(t)
for thread in threads:
# thread.setDaemon(True)
thread.start()
try:
for thread in threads:
if thread.is_alive():
thread.join()
# while True:
# for thread in threads:
# if thread.is_alive():
# pass
except KeyboardInterrupt, e:
print "User Stop"
print "Main is Done"

我们执行一下看,发现并不能使用ctrl-c使其中断。因为join()函数会让主线程一直阻塞,直到使用join()函数的线程终止。 我们看一下官方文档

Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates – either normally or through an unhandled exception – or until the optional timeout occurs.

所以如果我们想在主线程中通过ctrl-c来终止,使用join()是不可行的。

那么setDaemon()函数呢? 这个函数一定要在start()函数前使用。它将生成一个守护线程。即如果主线程被Kill掉,那么子线程也被会Kill掉。

main函数如下时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def main():
threads = []
for i in range(5):
t = TestDaemon(i)
threads.append(t)
for thread in threads:
thread.setDaemon(True)
thread.start()
try:
# while True:
for thread in threads:
if thread.is_alive():
pass
except KeyboardInterrupt, e:
print "User Stop"
print "Main is Done"

输出为:

1
2
3
4
5
6
Threading number : 0
Threading number : 1
Threading number : 2
Threading number : 3
Threading number : 4
Main is Done

可以看出,随着主线程的结束,所有setDaemon的线程也结束,并未被其定义while循环阻塞住。
如果我们添加到while中

main函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def main():
threads = []
for i in range(5):
t = TestDaemon(i)
threads.append(t)
for thread in threads:
thread.setDaemon(True)
thread.start()
try:
while True:
for thread in threads:
if thread.is_alive():
pass
except KeyboardInterrupt, e:
print "User Stop"
print "Main is Done"

输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Threading number : 4
Threading number : 3
Threading number : 2
Threading number : 0
Threading number : 4
Threading number : 1
Threading number : 2
Threading number : 3
Threading number : 0
Threading number : 4
Threading number : 1
Threading number : 3
Threading number : 2
^CUser Stop
Main is Done
----------------------

可以看到我们的User Stop已经输出,并且程序也结束了。
当然我们还可以对某些进程设置为join或者setDaemon

文章目录
|