python多程序的理解 multiprocessing Process join run
multiprocessing模組。 multiprocessing模組會在windows上時模擬出fork的效果,可以實現跨平臺,所以大多數都使用multiprocessing。
下面給一段簡單的程式碼,演示一下建立程序:
#encoding:utf-8 from multiprocessing import Process import os, time, random #執行緒啟動後實際執行的程式碼塊 def r1(process_name): for i in range(5): print process_name, os.getpid() #打印出當前程序的id time.sleep(random.random()) def r2(process_name): for i in range(5): print process_name, os.getpid() #打印出當前程序的id time.sleep(random.random()) if __name__ == "__main__": print "main process run..." p1 = Process(target=r1, args=(‘process_name1‘, )) #target:指定程序執行的函式,args:該函式的引數,需要使用tuple p2 = Process(target=r2, args=(‘process_name2‘, )) p1.start() #通過呼叫start方法啟動程序,跟執行緒差不多。 p2.start() #但run方法在哪呢?待會說。。。 p1.join() #join方法也很有意思,尋思了一下午,終於理解了。待會演示。 p2.join() print "main process runned all lines..."
執行結果:
上面提到了兩個方法:run 和join
run:如果在建立Process物件的時候不指定target,那麼就會預設執行Process的run方法:
#encoding:utf-8 from multiprocessing import Process import os, time, random def r(): print ‘run method‘ if __name__ == "__main__": print "main process run..." #沒有指定Process的targt p1 = Process() p2 = Process() #如果在建立Process時不指定target,那麼執行時沒有任何效果。因為預設的run方法是判斷如果不指定target,那就什麼都不做 #所以這裡手動改變了run方法 p1.run = r p2.run = r p1.start() p2.start() p1.join() p2.join() print "main process runned all lines..."
另:python原始碼裡,Process.run方法:
執行結果:
可見如果在例項化Process時不指定target,就會執行預設的run方法。
還有一個join方法:
最上面演示的程式碼中,在呼叫Process的start方法後,呼叫了兩次join方法。這個join方法是幹什麼的呢?
官方文件的意思是:阻塞當前程序,直到呼叫join方法的那個程序執行完,再繼續執行當前程序。
比如還是剛才的程式碼,只是把兩個join註釋掉了:
#encoding:utf-8 from multiprocessing import Process import os, time, random def r1(process_name): for i in range(5): print process_name, os.getpid() #打印出當前程序的id time.sleep(random.random()) def r2(process_name): for i in range(5): print process_name, os.getpid() #打印出當前程序的id time.sleep(random.random()) if __name__ == "__main__": print "main process run..." p1 = Process(target=r1, args=(‘process_name1‘, )) p2 = Process(target=r2, args=(‘process_name2‘, )) p1.start() p2.start() #p1.join() #p2.join() print "main process runned all lines..."
執行結果:
發現主程序不像之前那樣,等待兩個子程序執行完了,才繼續執行。而是啟動兩個程序後立即向下執行。
為了深刻理解,這次把p2的執行函式裡面睡眠時間調大,讓他多睡一會,然後保留p1的join,註釋掉p2的join,效果更明顯:
#encoding:utf-8
from multiprocessing import Process
import os, time, random
def r1(process_name):
for i in range(5):
print process_name, os.getpid() #打印出當前程序的id
time.sleep(random.random())
def r2(process_name):
for i in range(5):
print process_name, os.getpid() #打印出當前程序的id
time.sleep(random.random()*2)
if __name__ == "__main__":
print "main process run..."
p1 = Process(target=r1, args=(‘process_name1‘, ))
p2 = Process(target=r2, args=(‘process_name2‘, ))
p1.start()
p2.start()
p1.join()
#p2.join()
print "main process runned all lines..."
執行結果:
發現主執行緒只是等待p1完成了,就會向下執行,而不會等待p2是否完成。
所以使用多程序的常規方法是,先依次呼叫start啟動程序,再依次呼叫join要求主程序等待子程序的結束。
然而為什麼要先依次呼叫start再呼叫join,而不是start完了就呼叫join呢,如下:
由:
p1.start() p2.start() p1.join()
改為:
p1.start() p1.join() p2.start()
執行效果:
發現是先執行完p1,再執行主執行緒,最後才開始p2。
今天上午一直困惑這個事,現在終於明白了。join是用來阻塞當前執行緒的,p1.start()之後,p1就提示主執行緒,需要等待p1結束才向下執行,那主執行緒就乖乖的等著啦,自然沒有執行p2.start()這一句啦,當然就變成了圖示的效果了。