關於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方法前設置。

發佈了50 篇原創文章 · 獲贊 58 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章