python多執行緒實現

axj20發表於2017-10-22

本人初學者開始第一篇部落格,記錄學習的點點滴滴,以作為備忘錄,也希望能同大家一起分享。有理解錯誤的地方希望大家指正。 python中的多執行緒我參考了(http://www.cnblogs.com/fnng/p…)中的介紹,介紹的很入門很詳細。介紹了threading的基本用法。

最簡單的情況是:

import threading
import time
def fuction(i):
    print("我是第%s個程式,開始時間是%s"%(i+1,time.ctime()))
    time.sleep(2)               #子程式等2秒。。
    print("我是第%s個程式,結束時間是%s"%(i+1,time.ctime()))
threads=[threading.Thread(target=fuction,args=(i,) ) for i in range(5)]
for t in threads:
    t.start()
print("程式結束,%s:"%(time.ctime()))

#輸出為-------------------
我是第1個程式,開始時間是Sun Oct 22 17:45:37 2017
我是第2個程式,開始時間是Sun Oct 22 17:45:37 2017
我是第3個程式,開始時間是Sun Oct 22 17:45:37 2017
我是第4個程式,開始時間是Sun Oct 22 17:45:37 2017
我是第5個程式,開始時間是Sun Oct 22 17:45:37 2017
**程式結束,Sun Oct 22 17:45:37 2017:**          #主執行緒繼續執行,不等待,也不殺死子執行緒
我是第1個程式,結束時間是Sun Oct 22 17:45:39 2017
我是第2個程式,結束時間是Sun Oct 22 17:45:39 2017
我是第5個程式,結束時間是Sun Oct 22 17:45:39 2017
我是第3個程式,結束時間是Sun Oct 22 17:45:39 2017
我是第4個程式,結束時間是Sun Oct 22 17:45:39 2017

這裡介紹另外兩個函式:setDaemon()、join()
join:如在一個執行緒B中呼叫threada.join(),則threada結束後,執行緒B才會接著threada.join()往後執行。
setDaemon:主執行緒A啟動了子執行緒B,呼叫b.setDaemaon(True),則主執行緒結束時,會把子執行緒B也殺死,與C/C++中得預設效果是一樣的。

比如我想讓主程式等待子程式完成之後再執行,可以是用t.join()
其中t是指某個子程式,如t1,t2….然後join()可以有一個引數,主程式等待多少秒,如t1.join(2)指在t1子程式開始後,主程式等待2秒就繼續執行。

def fuction(i):
    print("我是第%s個程式,開始時間是%s"%(i+1,time.ctime()))
    time.sleep(i*2)               #模擬子程式的執行時間,ID越大時間越長
    print("我是第%s個程式,結束時間是%s"%(i+1,time.ctime()))
threads=[threading.Thread(target=fuction,args=(i,) ) for i in range(5)]
for t in threads:
    t.start()
threads[1].join(1)              #主程式在第二個子程式開始後阻塞1秒再執行
print("主程式:,%s:"%(time.ctime()))

#輸出---------------------
我是第1個程式,開始時間是Sun Oct 22 18:12:14 2017
我是第1個程式,結束時間是Sun Oct 22 18:12:14 2017
我是第2個程式,開始時間是Sun Oct 22 18:12:14 2017     #第二個子程式14秒開始
我是第3個程式,開始時間是Sun Oct 22 18:12:14 2017
我是第4個程式,開始時間是Sun Oct 22 18:12:14 2017
我是第5個程式,開始時間是Sun Oct 22 18:12:14 2017
主程式:Sun Oct 22 18:12:15 2017:                  #主程式在阻塞一秒後的15秒開始啟動執行
我是第2個程式,結束時間是Sun Oct 22 18:12:16 2017
我是第3個程式,結束時間是Sun Oct 22 18:12:18 2017
我是第4個程式,結束時間是Sun Oct 22 18:12:20 2017
我是第5個程式,結束時間是Sun Oct 22 18:12:22 2017

若想等所有的子程式都完成後,主程式在進行可以,簡單情況可以用最慢的一個子程式來對主程式進行阻塞,這裡最慢的是第5個子程式。可以:threads[4].join()。

import tensorflow as tf
import numpy as np
import random
import threading
import time


def fuction(i):
    print("我是第%s個程式,開始時間是%s"%(i+1,time.ctime()))
    time.sleep((i+0.5)*2)               #模擬子程式執行隨機秒
    print("我是第%s個程式,結束時間是%s"%(i+1,time.ctime()))
threads=[threading.Thread(target=fuction,args=(i,) ) for i in range(5)]
for t in threads:
    t.start()
threads[4].join()
print("主程式:%s:"%(time.ctime()))

#輸出-----------------------
我是第1個程式,開始時間是Sun Oct 22 18:29:28 2017
我是第2個程式,開始時間是Sun Oct 22 18:29:28 2017
我是第3個程式,開始時間是Sun Oct 22 18:29:28 2017
我是第4個程式,開始時間是Sun Oct 22 18:29:28 2017
我是第5個程式,開始時間是Sun Oct 22 18:29:28 2017
我是第1個程式,結束時間是Sun Oct 22 18:29:29 2017
我是第2個程式,結束時間是Sun Oct 22 18:29:31 2017
我是第3個程式,結束時間是Sun Oct 22 18:29:33 2017
我是第4個程式,結束時間是Sun Oct 22 18:29:35 2017
我是第5個程式,結束時間是Sun Oct 22 18:29:37 2017
主程式:Sun Oct 22 18:29:37 2017:                      #主程式等到最後一個子程式結束後才執行

另一種情況是,比如我想讓主程式執行完就立刻結束,殺死子程式:可以用t.setDaemon(True)

def fuction(i):
    print("我是第%s個程式,開始時間是%s"%(i+1,time.ctime()))
    time.sleep((i+0.5)*2)               #模擬子程式執行隨機秒
    print("我是第%s個程式,結束時間是%s"%(i+1,time.ctime()))
threads=[threading.Thread(target=fuction,args=(i,) ) for i in range(5)]

for t in threads:
    t.setDaemon(True)
    t.start()
print("主程式:%s:"%(time.ctime()))

#輸出---------------------------------
我是第1個程式,開始時間是Sun Oct 22 19:04:06 2017
我是第2個程式,開始時間是Sun Oct 22 19:04:06 2017
我是第3個程式,開始時間是Sun Oct 22 19:04:06 2017
我是第4個程式,開始時間是Sun Oct 22 19:04:06 2017
我是第5個程式,開始時間是Sun Oct 22 19:04:06 2017
主程式:Sun Oct 22 19:04:06 2017:                 #可以看到主執行緒完成後,後面就沒有子執行緒了。

一種特殊情況請注意:當並非像上面每個子程式一樣都設定t.setDaemon(True)(有的設定有的沒有。。)
如:

threads[2].setDaemon(True)   #只設定了第3個和第5個,1,2,4沒有設定這隻會kill掉第5個子執行緒
                             #個人猜測,當程式執行完主執行緒後則會檢查剩餘的子執行緒,將最後面的                             
threads[4].setDaemon(True)   #且是setDaemon(True) 子程式刪掉。第3個沒有kill掉是因為4執行緒還在執行
for t in threads:            #並且4是預設狀態不能被kill的。這時主程式依然在等待4完成而不會
    t.start()                #殺掉剩餘程式,當4完成了,就不等待了直接殺掉剩餘程式

我們可以這樣驗證,線上程4結束前看看執行緒5是否存活:

import tensorflow as tf
import numpy as np
import random
import threading
import time


def fuction(i):
    print("我是第%s個程式,開始時間是%s"%(i+1,time.ctime()))
    time.sleep((i+0.5)*2)               #模擬子程式執行隨機秒
    print("我是第%s個程式,結束時間是%s"%(i+1,time.ctime()))
    if i ==3:
        print("我是第4個程式:結束前程式5的狀態是:" ,threads[4].is_alive())   #加這一句判斷現成物
                                                                            #的存活情況
threads=[threading.Thread(target=fuction,args=(i,) ) for i in range(5)]

#threads[0].setDaemon(True)
#threads[1].setDaemon(True)
threads[2].setDaemon(True)
#threads[3].setDaemon(True)
threads[4].setDaemon(True)

for t in threads:
    t.start()
print("主程式:%s:"%(time.ctime()))

#輸出----------------------------------
我是第1個程式,開始時間是Sun Oct 22 19:22:36 2017
我是第2個程式,開始時間是Sun Oct 22 19:22:36 2017
我是第3個程式,開始時間是Sun Oct 22 19:22:36 2017
我是第4個程式,開始時間是Sun Oct 22 19:22:36 2017
我是第5個程式,開始時間是Sun Oct 22 19:22:36 2017
主程式:Sun Oct 22 19:22:36 2017:
我是第1個程式,結束時間是Sun Oct 22 19:22:37 2017
我是第2個程式,結束時間是Sun Oct 22 19:22:39 2017
我是第3個程式,結束時間是Sun Oct 22 19:22:41 2017
我是第4個程式,結束時間是Sun Oct 22 19:22:43 2017
我是第4個程式:結束前程式5的狀態是: True        #可以看到,此時執行緒5還是存活的,但4結束後5就消失了。

最後一種應用時,我們希望主程式等待某幾個子執行緒先執行完後在執行,並且殺死剩餘沒有完成的程式,可以用setDaemon()、join() 組合的方式:
如:完整執行完第1,2,3執行緒,之後執行主執行緒,主執行緒完成後殺死剩餘的子執行緒:

def fuction(i):
    print("我是第%s個程式,開始時間是%s"%(i+1,time.ctime()))
    time.sleep((i+0.5)*2)               #模擬子程式執行隨機秒
    print("我是第%s個程式,結束時間是%s"%(i+1,time.ctime()))
    if i ==3:
        print("我是第4個程式:結束前程式5的狀態是:" ,threads[4].is_alive())
threads=[threading.Thread(target=fuction,args=(i,) ) for i in range(5)]

#threads[0].setDaemon(True)
#threads[1].setDaemon(True)
#threads[2].setDaemon(True)
threads[3].setDaemon(True)          #設定第4和5子執行緒為可以kill的執行緒
threads[4].setDaemon(True)

for t in threads:
    t.start()
threads[0].join()                  #設定第1,2,3執行緒阻塞主執行緒的子執行緒
threads[1].join()
threads[2].join()
print("主程式:%s:"%(time.ctime()))

#輸出--------------------------
我是第1個程式,開始時間是Sun Oct 22 19:32:24 2017
我是第2個程式,開始時間是Sun Oct 22 19:32:24 2017
我是第3個程式,開始時間是Sun Oct 22 19:32:24 2017
我是第4個程式,開始時間是Sun Oct 22 19:32:24 2017
我是第5個程式,開始時間是Sun Oct 22 19:32:24 2017
我是第1個程式,結束時間是Sun Oct 22 19:32:25 2017
我是第2個程式,結束時間是Sun Oct 22 19:32:27 2017
我是第3個程式,結束時間是Sun Oct 22 19:32:29 2017
主程式:Sun Oct 22 19:32:29 2017:                #我們可以看到只完成了第1,2,3執行緒,然後最後是主執行緒

這篇文章就到這裡,python中子執行緒的暫停,阻塞,關閉,和喚醒,本人都不是很明確,如有好方法希望大家一起交流。我先寫在這裡。對於tensorflow中的讀取資料執行緒控制,等我整理在下一篇部落格。

相關文章