多執行緒《三》join方法
阿新 • • 發佈:2018-12-11
一 Process物件的join方法
在主程序執行過程中如果想併發地執行其他的任務,我們可以開啟子程序,此時主程序的任務與子程序的任務分兩種情況
情況一:在主程序的任務與子程序的任務彼此獨立的情況下,主程序的任務先執行完畢後,主程序還需要等待子程序執行完畢,然後統一回收資源。
情況二:如果主程序的任務在執行到某一個階段時,需要等待子程序執行完畢後才能繼續執行,就需要有一種機制能夠讓主程序檢測子程序是否執行完畢,在子程序執行完畢後才繼續執行,否則一直在原地阻塞,這就是join方法的作用
from multiprocessing import Process import time import random import os def task(): print('%s is piaoing' %os.getpid()) time.sleep(random.randrange(1,3)) print('%s is piao end' %os.getpid()) if __name__ == '__main__': p=Process(target=task) p.start() p.join() #等待p停止,才執行下一行程式碼 print('主')
有了join,程式不就是串行了嗎???
from multiprocessing import Process import time import random def task(name): print('%s is piaoing' %name) time.sleep(random.randint(1,3)) print('%s is piao end' %name) if __name__ == '__main__': p1=Process(target=task,args=('egon',)) p2=Process(target=task,args=('alex',)) p3=Process(target=task,args=('yuanhao',)) p4=Process(target=task,args=('wupeiqi',)) p1.start() p2.start() p3.start() p4.start() # 有的同學會有疑問: 既然join是等待程序結束, 那麼我像下面這樣寫, 程序不就又變成序列的了嗎? # 當然不是了, 必須明確:p.join()是讓誰等? # 很明顯p.join()是讓主執行緒等待p的結束,卡住的是主程序而絕非子程序p, p1.join() p2.join() p3.join() p4.join() print('主')
詳細解析如下:
程序只要start就會在開始運行了,所以p1-p4.start()時,系統中已經有四個併發的程序了
而我們p1.join()是在等p1結束,沒錯p1只要不結束主執行緒就會一直卡在原地,這也是問題的關鍵
join是讓主執行緒等,而p1-p4仍然是併發執行的,p1.join的時候,其餘p2,p3,p4仍然在執行,等#p1.join結束,可能p2,p3,p4早已經結束了,這樣p2.join,p3.join.p4.join直接通過檢測,無需等待
所以4個join花費的總時間仍然是耗費時間最長的那個程序執行的時間
上述啟動程序與join程序可以簡寫為
p_l=[p1,p2,p3,p4] for p in p_l: p.start() for p in p_l: p.join()
二 Process物件的其他屬性或方法
程序物件的其他方法一:terminate與is_alive
from multiprocessing import Process
import time
import random
def task(name):
print('%s is piaoing' %name)
time.sleep(random.randrange(1,5))
print('%s is piao end' %name)
if __name__ == '__main__':
p1=Process(target=task,args=('egon',))
p1.start()
p1.terminate()#關閉程序,不會立即關閉,所以is_alive立刻檢視的結果可能還是存活
print(p1.is_alive()) #結果為True
print('主')
print(p1.is_alive()) #結果為False
程序物件的其他屬性:name與pid
from multiprocessing import Process
import time
import random
def task(name):
print('%s is piaoing' %name)
time.sleep(random.randrange(1,5))
print('%s is piao end' %name)
if __name__ == '__main__':
p1=Process(target=task,args=('egon',),name='子程序1') #可以用關鍵引數來指定程序名
p1.start()
print(p1.name,p1.pid,)
三 練習題
1、改寫下列程式,分別別實現下述列印效果
from multiprocessing import Process
import time
import random
def task(n):
time.sleep(random.randint(1,3))
print('-------->%s' %n)
if __name__ == '__main__':
p1=Process(target=task,args=(1,))
p2=Process(target=task,args=(2,))
p3=Process(target=task,args=(3,))
p1.start()
p2.start()
p3.start()
print('-------->4')
效果一:保證最先輸出-------->4
-------->4
-------->1
-------->3
-------->2
效果二:保證最後輸出-------->4
-------->2
-------->3
-------->1
-------->4
效果三:保證按順序輸出
-------->1
-------->2
-------->3
-------->4
2、判斷上述三種效果,哪種屬於併發,哪種屬於序列?