這段時間一直在用
Python
寫一個遊戲的伺服器程式。在編寫過程中,不可避免的要用多線程來處理與用戶端的互動。
Python
標準庫提供了
thread
和
threading
兩個模組來對多線程進行支援。其中,
thread
模組以低級、原始的方式來處理和控制線程,而
threading
模組通過對
thread
進行二次封裝,提供了更方便的
api
來處理線程。
雖然使用
thread
沒有
threading
來的方便,但它更靈活。今天先介紹
thread
模組的基本使用,下一篇
將介紹
threading
模組。
在介紹
thread
之前,先看一段代碼,猜猜程式運行完成之後,在控制台上輸出的結果是什嗎?
#coding=gbk<br />import thread, time, random<br />count = 0<br />def threadTest():<br /> global count<br /> for i in xrange(10000):<br /> count += 1<br />for i in range(10):<br /> thread.start_new_thread(threadTest, ())#如果對start_new_thread函數不是很瞭解,不要著急,馬上就會講解<br />time.sleep(3)<br />print count#count是多少呢?是10000 * 10 嗎?<br />
thread.start_new_thread
(
function
,
args
[
,
kwargs
]
)
函數將建立一個新的線程,並返回該線程的標識符(標識符為整數)。參數
function
表示線程建立之後,立即執行的函數,參數
args
是該函數的參數,它是一個元群組類型;第二個參數
kwargs
是可選的,它為函數提供了具名引數字典。函數執行完畢之後,線程將自動結束。如果函數在執行過程中遇到未處理的異常,該線程將退出,但不會影響其他線程的執行。
下面是一個簡單的例子:
#coding=gbk<br />import thread, time<br />def threadFunc(a = None, b = None, c = None, d = None):<br /> print time.strftime('%H:%M:%S', time.localtime()), a<br /> time.sleep(1)<br /> print time.strftime('%H:%M:%S', time.localtime()), b<br /> time.sleep(1)<br /> print time.strftime('%H:%M:%S', time.localtime()), c<br /> time.sleep(1)<br /> print time.strftime('%H:%M:%S', time.localtime()), d<br /> time.sleep(1)<br /> print time.strftime('%H:%M:%S', time.localtime()), 'over'</p><p>thread.start_new_thread(threadFunc, (3, 4, 5, 6))#建立線程,並執行threadFunc函數。<br />time.sleep(5)<br />
thread.exit
()
結束當前線程。調用該函數會觸發
SystemExit
異常,如果沒有處理該異常,線程將結束。
thread.get_ident
()
返回當前線程的標識符,標識符是一個非零整數。
thread.interrupt_main
()
在主線程中觸發
KeyboardInterrupt
異常。子線程可以使用該方法來中斷主線程。下面的例子示範了在子線程中調用
interrupt_main
,在主線程中捕獲異常
:
import thread, time<br />thread.start_new_thread(lambda : (thread.interrupt_main(), ), ())<br />try:<br /> time.sleep(2)<br />except KeyboardInterrupt, e:<br /> print 'error:', e<br />print 'over'<br />
下面介紹
thread
模組中的瑣,瑣可以保證在任何時刻,最多隻有一個線程可以訪問共用資源。
thread.LockType
是
thread
模組中定義的瑣類型。它有如下方法:
lock.acquire
(
[
waitflag
]
)
擷取瑣。函數返回一個布爾值,如果擷取成功,返回
True
,否則返回
False
。參數
waitflag
的預設值是一個非零整數,表示如果瑣已經被其他線程佔用,那麼當前線程將一直等待,只到其他線程釋放,然後擷取訪瑣。如果將參數
waitflag
置為
0
,那麼當前線程會嘗試擷取瑣,不管瑣是否被其他線程佔用,當前線程都不會等待。
lock.release
()
釋放所佔用的瑣。
lock.locked
()
判斷瑣是否被佔用。
現在我們回過頭來看文章開始處給出的那段代碼:代碼中定義了一個函數
threadTest
,它將全域變數逐一的增加
10000
,然後在主線程中開啟了
10
個子線程來調用
threadTest
函數。但結果並不是預料中的
10000 * 10
,原因主要是對
count
的並行作業引來的。全域變數
count
是共用資源,對它的操作應該串列的進行。下面對那段代碼進行修改,在對
count
操作的時候,進行加瑣處理。看看程式啟動並執行結果是否和預期一致。修改後的代碼:
#coding=gbk<br />import thread, time, random<br />count = 0<br />lock = thread.allocate_lock() #建立一個瑣對象<br />def threadTest():<br /> global count, lock<br /> lock.acquire() #擷取瑣</p><p> for i in xrange(10000):<br /> count += 1</p><p> lock.release() #釋放瑣<br />for i in xrange(10):<br /> thread.start_new_thread(threadTest, ())<br />time.sleep(3)<br />print count<br />
thread模組是不是並沒有想像中的那麼難!簡單就是美,這就是Python。更多關於thread模組的內容,請參考Python手冊 thread
模組