1. 程式人生 > >python多執行緒程式設計(二)--threading模組

python多執行緒程式設計(二)--threading模組

threading模組物件

物件

描述

Thread

一個執行緒的執行物件

Lock

鎖物件

RLock

可重入鎖物件,使單執行緒可以再次獲得已經獲得了的鎖(遞迴鎖定)

Condition

條件變數,讓一個執行緒停下來,等待其它執行緒滿足了某個條件

Event

事件物件,通用的條件變數

Semaphore

訊號量

BoundedSemaphore

Semaphore類似,只是它不允許超過初始值

Timer

Thread相似,不過它要等待一段時間才開始執行

threadingThread類是最主要的執行物件。

Thread

物件的函式

函式

描述

start()

執行緒開始執行

run()

執行緒功能函式

join(timeout=None)

程式掛起,直到執行緒結束;如果給了timeout,則最多阻塞timeout

getName()

返回執行緒名字

setName(name)

設定執行緒名字

isAlive()

這個執行緒是否還在執行

isDaemon()

返回執行緒的daemon標誌

setDaemon(daemonic)

設定執行緒的daemon屬性,一定要在呼叫start()函式前呼叫

使用Thread類,我們介紹三種方法來建立執行緒。

●       建立一個Thread的例項,傳給它一個函式

●       建立一個Thread的例項,傳給它一個可呼叫的類物件

●       Thread派生出一個子類,建立一個這個子類的例項

下面看第一種,建立一個Thread的例項,傳給它一個函式

我們將初始化一個Thread物件,把函式(及其引數)傳進去。這種方式例項化一個Thread與呼叫thread.start_new_thread()之間的最大區別就是,新執行緒不會立即開始。當你建立執行緒物件又不想立即開始執行的時候,這是很有用的。

#coding: utf-8
import threading
from time import sleep, ctime

loops = [4,2]

def  loop(nloop, nsec):
	print 'loop', nloop, 'start at:', ctime()
	print 'loop %d 掛起%d秒' % (nloop, nsec)
	sleep(nsec)
	print 'loop', nloop, 'done at:', ctime()

def main():
	print 'main thread start!'
	threads = []  #執行緒列表
	nloops = range(len(loops))

	for i in nloops:
		t = threading.Thread(target=loop, args=(i, loops[i]))
		threads.append(t)

	for i in nloops:
		threads[i].start()

	for i in nloops:
		threads[i].join()  #等待執行緒結束

	print 'all done at:', ctime()

if __name__ == '__main__':
	main()

執行結果:


這種方式就省了管理一堆鎖的功夫了,只要對每個執行緒呼叫join()函式,就會等到執行緒結束。

另外,如果你的主執行緒除了等執行緒結束外,還有其它的事情要做(如處理或等待其它的客戶請求),那就不用呼叫join()。一旦執行緒啟動後,就會一直執行,直到執行緒的函式結束,退出為止。所以只有在你要等待執行緒結束的時候才要呼叫join()

第二種方式,建立一個Thread的例項,傳給它一個可呼叫的類物件

這種方式就是在第一種方式的情況下,將函式封裝進類物件裡面,由類物件提供功能函式。在建立Thread物件時會例項化這個類物件。

#coding: utf-8
import threading
from time import sleep, ctime

loops = [4,2]

class Func(object):
	def __init__(self, func, args, name=""):
		self.name = name
		self.func = func
		self.args =args

	def __call__(self):
		self.res = self.func(*self.args)  #如果python版本是1.6以下,就使用apply(self.func, self.args)

def  loop(nloop, nsec):
	print 'loop', nloop, 'start at:', ctime()
	print 'loop %d 掛起%d秒' % (nloop, nsec)
	sleep(nsec)
	print 'loop', nloop, 'done at:', ctime()

def main():
	print 'main thread start!'
	threads = []  #執行緒列表
	nloops = range(len(loops))

	for i in nloops:
		t = threading.Thread(target=Func(loop, (i, loops[i]), loop.__name__))
		threads.append(t)

	for i in nloops:
		threads[i].start()

	for i in nloops:
		threads[i].join()  #等待執行緒結束

	print 'all done at:', ctime()

if __name__ == '__main__':
	main()

建立新執行緒的時候,Thread物件會呼叫我們的Func物件,這時會用到一個特殊函式__call__()這是python的一個特性,只要定義型別的時候,實現__call__函式,這個型別就成為可呼叫的。比如實現了__call__函式的Func物件例項instance,形如instance(arg1,arg2,...)實際上呼叫的就是instance.__call__(arg1,arg2,...)

第三種方式,Thread派生出一個子類,建立這個子類的例項

#coding: utf-8
import threading
from time import sleep, ctime

loops = [4,2]

class MyThread(threading.Thread):
	def __init__(self, func, args, name=""):
		threading.Thread.__init__(self)
		self.name = name
		self.func = func
		self.args =args

	def run(self):
		self.res = self.func(*self.args)
		
def  loop(nloop, nsec):
	print 'loop', nloop, 'start at:', ctime()
	print 'loop %d 掛起%d秒' % (nloop, nsec)
	sleep(nsec)
	print 'loop', nloop, 'done at:', ctime()

def main():
	print 'main thread start!'
	threads = []
	nloops = range(len(loops))

	for i in nloops:
		t = MyThread(loop, (i, loops[i]), loop.__name__)
		threads.append(t)

	for i in nloops:
		threads[i].start()

	for i in nloops:
		threads[i].join()

	print 'all done at:', ctime()

if __name__ == '__main__':
	main()

這種方式使建立執行緒物件的程式碼更簡潔。