不喜歡廢話,先上今天的代碼!python
#-*- coding:utf-8 -*- import threading class MyThreading(threading.Thread): def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): print self.num t = MyThreading(100) t.start() print t.isAlive()
乍一看,很簡單的threading代碼。首先咱們繼承了Thread類,在子類裏初始化後又重寫了run方法。最後咱們實例化MyThreading子類,而後打印咱們的num參數。最後再打印線程執行狀態。app
初學者一看,絕對分爲2派:一、支持說先打印num參數,而後纔打印線程狀態。 二、拍胸脯保證先打印線程狀態再打印num參數;函數
其實結果出人預料:ui
結果1:spa
C:\Python27\python.exe D:/ProjectSpace/thread-example.py 100True Process finished with exit code 0
結果2:線程
C:\Python27\python.exe D:/ProjectSpace/thread-example.py True100 Process finished with exit code 0
吃驚嗎?也許每次運行結果可能會有幾回相同,可是在運行10次內,至少會有1-4次不一樣結果。debug
答案:線程的執行將是無序的調試
帶着上面的問題,咱們繼續看下面一個例子:code
#-*- coding:utf-8 -*- import threading,time class MyThreading(threading.Thread): def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): time.sleep(10) print self.num def function1(): t1.start() time.sleep(1) print "t1 thread was Destruction " def function2(): t2.start() time.sleep(1) print "t2 thread was Destruction " t1 = MyThreading(10) t2 = MyThreading(20) t2.setDaemon(True) function1() function2()
當你屢次運行代碼的時候,大概你能看到以下結果:繼承
C:\Python27\python.exe D:/ProjectSpace/thread-example.py t1 thread was Destruction t2 thread was Destruction 10 Process finished with exit code 0
讓咱們看看單步調試運行下的結果是怎麼樣的:
C:\Python27\python.exe "C:\Program Files (x86)\JetBrains\PyCharm 5.0.3\helpers\pydev\pydevd.py" --multiproc --qt-support --client 127.0.0.1 --port 62267 --file D:/ProjectSpace/thread-example.py Connected to pydev debugger (build 143.1559) 10 t1 thread was Destruction 20 t2 thread was Destruction Process finished with exit code 0
是的, 你沒有看錯! 出現不一樣的結果的緣由是:
Threadclass.setDeamon方法指定了一個線程爲主線程;而主線程的做用是當它要退出時會先檢查子進程是否完成,若是未完成則繼續等待,完成則退出。
這也是爲何咱們在Debug模式時走的是邏輯上的方法,而實際上在運行時的結果卻如上所述。
那麼問題來了!:咱們如何保證程序的順序執行呢?
爲了保證線程的執行順序或者說是爲了保證一致性,針對線程的操做引入了同步的概念。而針對同步最好的辦法也就是對操做進行加鎖了。(加鎖讓我想起了MySQL的鎖 - _ -)
請繼續看下面的2個例子:
例1:
#-*- coding:utf-8 -*- import threading,time ####繼承Thread類 class MyThreading(threading.Thread): def __init__(self,name): ####初始化父類 threading.Thread.__init__(self,name=name) def run(self): ####引入全局變量 global x ####給操做加鎖 lock.acquire() for i in range(3): x = x + 1 time.sleep(3) print x ####操做完成並解鎖 lock.release() ####實例化一個鎖的類 lock = threading.RLock() ####定義一個空的線程類的列表 tl = [] ####實例化10個類,而且將類添加到tl這個類列表裏 for i in range(10): t = MyThreading(str(i)) tl.append(t) ####初始化全局 x = 0 ####逐個執行全部已經實例化的線程 for i in tl: i.start()
輸出結果以下
C:\Python27\python.exe D:/ProjectSpace/thread-example.py 3 6 9 12 15 18 21 24 27 30 Process finished with exit code 0
代碼很簡單,首先經過一個循環實例化10個類放進一個列表內,再從列表內遍歷出來運行。 由於執行了加鎖——》釋放這個步驟。若是在time.sleep()時間內未到,release沒法執行。因此咱們能控制程序的順序。
例2:
#-*- coding:utf-8 -*- import threading,time ####繼承Thread類 class MyThreading(threading.Thread): def __init__(self,name): ####初始化父類 threading.Thread.__init__(self,name=name) def run(self): ####引入全局變量 global x ####給操做加鎖 #lock.acquire() for i in range(3): x = x + 1 time.sleep(3) print x ####操做完成解鎖 #lock.release() ####實例化一個鎖的類 #lock = threading.RLock() ####定義一個空的線程類的列表 tl = [] ####實例化10個類,而且將類添加到tl這個類列表裏 for i in range(10): t = MyThreading(str(i)) tl.append(t) ####初始化全局 x = 0 ####逐個執行全部已經實例化的線程 for i in tl: i.start()
輸出結果以下
C:\Python27\python.exe D:/ProjectSpace/thread-example.py 30 30 30 30 30 30 30 30 30 30 Process finished with exit code 0
同例1同樣,程序從列表拿出實例化的類運行;可是由於沒對run方法進行加鎖,因此線程運行到time.sleep()時不會等待就啓動第二個....第三個.....直到最後一個。
而當run方法所有運行完畢後,而且計算出全局變量X的最終值,time.sleep時間到了;這時候X已經爲30,因此每一個X輸出的值都是30了。
一個簡單的Threading函數同步實例就說到這裏! 下次見~~~ (— 3 —)