关于python线程模块threading的学习总结:threading.Thread对象的join方法

如果想了解什么是线程,推荐看一看这篇文章,真的是生动形象:趣文:我是一个线程

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方法前设置。

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值