赞
踩
如果想了解什么是线程,推荐看一看这篇文章,真的是生动形象:趣文:我是一个线程
1.子线程不使用join方法
join方法主要是会阻塞主线程,在子线程结束运行前,主线程会被阻塞等待。这里用一个例子来说明:
- # encoding=utf8
-
- import threading
- import time
-
- def now():
- return '%.3f' % time.time()
-
- def test(n):
- print 'start %s at: %s' % (n, now())
- time.sleep(n)
- print 'end %s at: %s' % (n, now())
-
- def main():
- print 'start main at: %s' % now()
- threadpool = []
- for i in xrange(1, 4):
- th = threading.Thread(target=test, args=(i,))
- threadpool.append(th)
- for th in threadpool:
- th.start()
- # for th in threadpool:
- # th.join()
- print 'main end at: %s' % now()
- if __name__ == '__main__':
- main()

在上面的例子中,每个子线程都会执行test方法,为了方便看结果,使每个子线程的sleep时间不同。
当前只是调用了每个子线程的start方法,并没有调用join方法,此时运行结果:
- start main at: 1521721709.912
- start 1 at: 1521721709.913
- start 2 at: 1521721709.913
- start 3 at: 1521721709.913
- main end at: 1521721709.913
- end 1 at: 1521721710.913
- end 2 at: 1521721711.913
- end 3 at: 1521721712.913
通过结果可以看出,主线程完成第一次打印后(start main at: 1521721709.912),其他子线程同时开始,但是主线程并没有等待子线程结束才结束,主线程继续执行第二次打印(main end at: 1521721709.913),接着其他子线程因为各自sleep的时间不同而相继结束。
2.子线程使用join方法
下面再看一下使用join方法后的结果(将上面注释掉的部分取消):
- start main at: 1521722097.382
- start 1 at: 1521722097.382
- start 2 at: 1521722097.382
- start 3 at: 1521722097.382
- end 1 at: 1521722098.382
- end 2 at: 1521722099.382
- end 3 at: 1521722100.383
- main end at: 1521722100.383
不难看出,主线程阻塞等待子线程完成后,自己才结束运行。
3.join方法的timeout参数
然后可以给在join函数传一个timeout参数的,看看它的作用是什么,这里修改了一下代码:
- # encoding=utf8
-
- import threading
- import time
-
- def now():
- return '%.3f' % time.time()
-
- def test(n):
- while 1:
- print str(n) * 6
- time.sleep(5)
-
- def main():
- print 'start main at: %s' % now()
- threadpool = []
- for i in xrange(1, 3):
- th = threading.Thread(target=test, args=(i, ))
- threadpool.append(th)
- for th in threadpool:
- th.start()
- for th in threadpool:
- th.join(5)
- print 'main end at: %s' % now()
- if __name__ == '__main__':
- main()

这里设置每个线程的timeout都是5,运行部分结果如下:
- start main at: 1521723210.825
- 111111
- 222222
- 222222
- 111111
- main end at: 1521723220.825
- 111111
- 222222
- 111111
- 222222
- ......
因为每个子线程执行的是一个while循环,实际上是会一直运行下去的(两个子线程一直打印111111,222222),如果不给join方法设置timeout,那么主线程会一直等下去,永远不会执行最后的“print 'main end at: %s' % now()”语句,但是上面的代码设置了timeout为5秒,通过执行结果可以看出,主线程一共等待了10秒后结束了自己的运行。所以可以知道,join方法的timeout参数表示了主线程被每个子线程阻塞等待的时间。
4.说说setDaemon
使用join方法是为了让主线程等待子线结束后再做其他事情,setDaemon方法正好相反,它是为了保证主线程结束的时候,整个进程就结束,不会等待所有子线程执行完才结束。修改一下上面的代码:
- # encoding=utf8
-
- import threading
- import time
-
- def now():
- return '%.3f' % time.time()
-
- def test(n):
- time.sleep(n)
- print '%s has ran' % (str(n) * 6)
-
- def main():
- print 'start main at: %s' % now()
- threadpool = []
- for i in xrange(2):
- th = threading.Thread(target=test, args=(i, ))
- threadpool.append(th)
- for th in threadpool:
- th.setDaemon(True)
- th.start()
- print 'main end at: %s' % now()
- if __name__ == '__main__':
- main()

以下是运行结果:
- start main at: 1521726104.773
- 000000 has ran
- main end at: 1521726104.773
通过结果可以看出,虽然创建了两个子线程,第一个子线程的sleep时间为0,所以可以和主线程同时执行,但是第二个子线程本身会先sleep1秒,这时候主线程已经执行完,整个程序退出,并没有接着执行第二个子线程。
需要注意的是,setDaemon方法要在调用start方法前设置。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。