1. 程式人生 > >Process物件的其它方法與屬性(join)

Process物件的其它方法與屬性(join)

一 Process物件的join方法

在主程序執行過程中如果想併發地執行其他的任務,我們可以開啟子程序,此時主程序的任務與子程序的任務分兩種情況

情況一:在主程序的任務與子程序的任務彼此獨立的情況下,主程序的任務先執行完畢後,主程序還需要等待子程序執行完畢,然後統一回收資源。

情況二:如果主程序的任務在執行到某一個階段時,需要等待子程序執行完畢後才能繼續執行,就需要有一種機制能夠讓主程序檢測子程序是否執行完畢,在子程序執行完畢後才繼續執行,否則一直在原地阻塞,這就是join方法的作用

# join方法
from multiprocessing import Process
import time
import os


def task(name):                                                               # os.getppid()檢視父程序編號
    print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid()))   # os.getpid()檢視自己程序編號
    time.sleep(3)   # 模擬任務執行一段時間
    print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid()))


if __name__ == "__main__":    # windows 一定要把開啟指令放到main下面  Linux無所謂
    # Process(target=task, kargs={"name" : "子程序"})  # 方式1
    p = Process(target=task, args=("子程序1",))  # 方式2  例項化得到一個物件
    p.start()    # (僅僅只是給作業系統傳送了一個訊號)開啟子程序,幫你執行task

    p.join()  # 主程序會等子程序執行(主程序基於子程序執行的結果進行後續程式碼的執行)
    print("主", os.getpid(), os.getppid())  # 此時的父程序是pycharm
    print(p.pid)   # p物件下的pid(驗證殭屍程序)

10952 is running, parent id is <8624>
10952 is done, parent id is <8624>
主 8624 124
10952

from multiprocessing import Process
import time
import os


def task(name, n):                                                               # os.getppid()檢視父程序編號
    print("%s is running" % name)   # os.getpid()檢視自己程序編號
    time.sleep(n)   # 模擬任務執行一段時間


if __name__ == "__main__":    # windows 一定要把開啟指令放到main下面  Linux無所謂
    start = time.time()
    p1 = Process(target=task, args=("子程序1", 5))
    p2 = Process(target=task, args=("子程序2", 3))
    p3 = Process(target=task, args=("子程序3", 2))
    p_l = [p1, p2, p3]

    # p1.start()    # (僅僅只是給作業系統傳送了一個訊號)開啟子程序,幫你執行task(不一定按順序)
    # p2.start()
    # p3.start()
    for i in p_l:   # 簡寫
        i.start()

    # p1.join()     # 讓主程序等,連續三個併發執行
    # p2.join()
    # p3.join()
    for p in p_l:
        p.join()

    print("主", (time.time()-start))  # 此時的父程序是pycharm

子程序1 is running
子程序2 is running
子程序3 is running
主 5.103978633880615

注意:

程序只要start就會在開始運行了,所以p1-p3.start()時,系統中已經有併發的程序了

join是讓主執行緒等,而p1-p3仍然是併發執行的,p1.join的時候,其餘p2,p3,p4仍然在執行,等#p1.join結束,可能p2,p3早已經結束了,這樣p2.join,p3.join直接通過檢測,無需等待

所以3個join花費的總時間仍然是耗費時間最長的那個程序執行的時間

序列

# 串聯執行
from multiprocessing import Process
import time
import os


def task(name, n):                                                               # os.getppid()檢視父程序編號
    print("%s is running" % name)   # os.getpid()檢視自己程序編號
    time.sleep(n)   # 模擬任務執行一段時間


if __name__ == "__main__":    # windows 一定要把開啟指令放到main下面  Linux無所謂
    start = time.time()
    p1 = Process(target=task, args=("子程序1", 5))
    p2 = Process(target=task, args=("子程序2", 3))
    p3 = Process(target=task, args=("子程序3", 2))

    p1.start()    # (僅僅只是給作業系統傳送了一個訊號)開啟子程序,幫你執行task(不一定按順序)
    p1.join()    # 主程式再等P1
    p2.start()    # p2 才開始
    p2.join()
    p3.start()
    p3.join()

    print("主", (time.time()-start))  # 此時的父程序是pycharm 

子程序1 is running
子程序2 is running
子程序3 is running
主 10.3139066696167


 

二 Process物件的其他屬性或方法

程序物件的其他方法一:is_alive

# 瞭解 p.is_alive()
from multiprocessing import Process
import time
import os


def task(name):                                                               # os.getppid()檢視父程序編號
    print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid()))   # os.getpid()檢視自己程序編號
    time.sleep(3)   # 模擬任務執行一段時間
    print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid()))


if __name__ == "__main__":    # windows 一定要把開啟指令放到main下面  Linux無所謂
    # Process(target=task, kargs={"name" : "子程序"})  # 方式1
    p = Process(target=task, args=("子程序1",))  # 方式2  例項化得到一個物件
    p.start()    # (僅僅只是給作業系統傳送了一個訊號)開啟子程序,幫你執行task

    print(p.is_alive())  # 判斷活著還是死的
    p.join()  # 主程序會等子程序執行(主程序基於子程序執行的結果進行後續程式碼的執行)
    print("主", os.getpid(), os.getppid())  # 此時的父程序是pycharm
    print(p.pid)   # p物件下的pid(驗證殭屍程序)
    print(p.is_alive())    # 判斷活著還是死的

 

程序物件的其他屬性:terminal

# 瞭解 p.terminate()
from multiprocessing import Process
import time
import os


def task(name):                                                               # os.getppid()檢視父程序編號
    print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid()))   # os.getpid()檢視自己程序編號
    time.sleep(3)   # 模擬任務執行一段時間
    print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid()))


if __name__ == "__main__":    # windows 一定要把開啟指令放到main下面  Linux無所謂
    # Process(target=task, kargs={"name" : "子程序"})  # 方式1
    p = Process(target=task, args=("子程序1",))  # 方式2  例項化得到一個物件
    p.start()    # (僅僅只是給作業系統傳送了一個訊號)開啟子程序,幫你執行task

    print("主")
    p.terminate()   # 給作業系統發出訊號終止程序
    time.sleep(3)
    print(p.is_alive())

程序物件的其他屬性:name

# 瞭解 p.name
from multiprocessing import Process
import time
import os


def task(name):                                                               # os.getppid()檢視父程序編號
    print("%s is running, parent id is <%s>" % (os.getpid(), os.getppid()))   # os.getpid()檢視自己程序編號
    time.sleep(3)   # 模擬任務執行一段時間
    print("%s is done, parent id is <%s>" % (os.getpid(), os.getppid()))


if __name__ == "__main__":    # windows 一定要把開啟指令放到main下面  Linux無所謂
    # Process(target=task, kargs={"name" : "子程序"})  # 方式1
    p = Process(target=task, args=("子程序1",), name="我的程序")  # 方式2  例項化得到一個物件
    p.start()    # (僅僅只是給作業系統傳送了一個訊號)開啟子程序,幫你執行task

    print("主")
    print(p.name)  # 檢視程序名稱(預設為Process-1)

 

三 練習題

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、判斷上述三種效果,哪種屬於併發,哪種屬於序列?