一.思路概述
Python線程建立
使用threading模組的Thread類的介面如下
class Thread( group=None, target=None, name=None, args=(), kwargs={})
需要關注的參數是target和args. target 是需要子線程啟動並執行目標函數,args是函數的參數,以tuple的形式傳遞。
以下代碼建立一個指向函數worker的子線程
def worker(tid,account):
...
th = threading.Thread(target=worker,args=(i,acc) ) ;
啟動這個線程
th.start()
等待線程返回或者回收線程資源
threading.Thread.join(th)
或者th.join()
如果你可以對要處理的資料進行很好的劃分,而且線程之間無須通訊,那麼你可以使用:建立=》運行=》回收的方式編寫你的多線程程式。但是如果線程之間需要訪問共同的對象,則需要引入互斥鎖或者訊號量對資源進行互斥訪問。
下面講講如何建立互斥鎖
建立鎖
g_mutex = threading.Lock()
....
使用鎖
for ... :
#鎖定,從下一句代碼到釋放前互斥訪問
g_mutex.acquire()
a_account.deposite(1)
#釋放
g_mutex.release()
二.業務需求
類比一個公交地鐵IC卡繳車費的多線程程式
假設有10個讀卡機,每個讀卡機收費器每次扣除使用者一塊錢進入總賬中,每個讀卡機每天一共被刷1000000次。賬戶原有100塊。所以最後的總賬應該為10000100。
三.源碼實現
#!/usr/bin/env python#encoding: utf-8import time, datetime, threading#each worker thread exec 1000000 timesdef worker(tid, account): global g_mutex for i in range(1000000): g_mutex.acquire() if i%500000 == 0: print 'worker thread', tid, 'count', i account.deposite(1) g_mutex.release()#account operation classclass Account: def __init__(self, base): self.m_amount = base def deposite(self, amount): self.m_amount += amount; def withdraw(self, amount): self.m_amount -= amount#main entry point...if __name__ == '__main__': global g_mutex count = 0; tm_start = datetime.datetime.now() print 'Main Thread start at:', tm_start #initialize thread pool thread_pool = [] #initialize mutex g_mutex = threading.Lock() #init thread items acc = Account(100) for i in range(10): t = threading.Thread(target=worker, args=(i, acc)); thread_pool.append(t) #start worker threads one by one for i in range(10): thread_pool[i].start() #reclaim all worker threads resource for i in range(10): threading.Thread.join(thread_pool[i]) #statistics tm_stop = datetime.datetime.now() print 'count=', acc.m_amount print 'Main Thread end at:', tm_stop print 'time consumption ', tm_stop-tm_start
四.運行效果截圖
注意在多線程環境下print輸出要放到互斥鎖下面操作,才不會導致導致各線程的列印資訊混亂.
參考文獻
[1].http://blog.csdn.net/liangpz521/article/details/8906861