1. 程式人生 > >多線程《三》join方法

多線程《三》join方法

and 查看 時間 簡寫 target 效果 end 就是 其余

一 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、判斷上述三種效果,哪種屬於並發,哪種屬於串行?

多線程《三》join方法