python實現守護進程、守護線程、守護非守護並行

@本文來源於公衆號:csdn2299,喜歡可以關注公衆號 程序員學府

本篇文章主要介紹了python實現守護進程、守護線程、守護非守護並行,詳細的介紹了守護子進程、非守護子進程並存,守護子線程非守護子進程並存的方法,具有一定的參考價值,感興趣的小夥伴們可以參考一下
守護進程

1、守護子進程

主進程創建守護進程
其一:守護進程會在主進程代碼執行結束後就終止
其二:守護進程內無法再開啓子進程,否則拋出異常:AssertionError: daemonic processes are not allowed to havechildren
注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止

我們來看一個例子

from multiprocessing import Process
import os,time,random
 
def task():
  print('%s is running' %os.getpid())
  time.sleep(2)
  print('%s is done' %os.getpid())
 
  #守護進程內無法再開啓子進程,否則拋出異常
  # p = Process(target=time.sleep, args=(3,))
  # p.start()
 
if __name__ == '__main__':
  p=Process(target=task)
  p.daemon = True #1、必須在p.start()之前
  p.start()
  print('主')

輸出結果如下:

原因是:主進程程序啓動執行到p子進程,由於子進程需要開闢內存空間,由於需要耗費時間,所以主進程會首先輸出“主”,由於主進程執行完畢,那麼守護子進程p也就被幹掉了,隨之主進程也就退出了

如果上面代碼修改如下,加上 p.join()這一行代碼

if __name__ == '__main__':
  p=Process(target=task)
  p.daemon = True #1、必須在p.start()之前
  p.start()
  p.join()
  print('主')

那麼程序會輸出如下:

14732 is running

14732 is done

join以前也分析過,是起到阻塞作用,子進程執行完畢,才執行主進程,所以加上join
1、執行到join,是起到阻塞作用,就會執行子進程,然後執行完畢,在執行主進程
2、也可以這樣理解,執行到join,由於主進程print(“主”)沒有執行完,所以守護進程不會被幹掉,繼續執行

1、守護子進程、非守護子進程並存

在上面的例子是子進程只有一個守護進程,在主進程執行完畢,守護子進程就會被幹掉 ,我們在來看一個,子進程既有守護子進程,又包含非守護子進程

from multiprocessing import Process
from threading import Thread
import time,os
def foo():
  print(123)
  time.sleep(1)
  print("end123")
 
def bar():
 
  print(456)
  time.sleep(3)
  print("end456")
 
if __name__ == '__main__':
  p1=Process(target=foo)
  p2 = Process(target=bar)
  p1.daemon=True
  p1.start()
  p2.start()
  print("main-------")

輸出如下:

main-------
456
end456

原因如下:由於p1,p2都是子進程,需要開闢內存空間,需要耗費時間,所以會優先輸出主進程“main”,由於p1是守護子進程,p2是非守護子進程,當主進程執行完畢(注意之類主進程還沒有退出,因爲還有p2非守護進程),p1守護進程也就退了,但是還有一個p2非守護進程,所以p2會執行自己的代碼任務,當p2執行完畢,那麼主進程也就退出了,進而整個程序就退出了

守護線程

守護子線程

無論是進程還是線程,都遵循:守護xxx會等待主xxx運行完畢後被銷燬
需要強調的是:運行完畢並非終止運行

1.對主進程來說,運行完畢指的是主進程代碼運行完畢
2.對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程纔算運行完畢

詳細解釋:
1 主進程在其代碼結束後就已經算運行完畢了(守護進程在此時就被回收),然後主進程會一直等非守護的子進程都運行完畢後回收子進程的資源(否則會產生殭屍進程),纔會結束,

2 主線程在其他非守護線程運行完畢後纔算運行完畢(守護線程在此時就被回收)。因爲主線程的結束意味着進程的結束,進程整體的資源都將被回收,而進程必須保證非守護線程都運行完畢後才能結束。

我們先來看一個例子

from multiprocessing import Process
from threading import Thread
import os,time,random
def task():
  # t=Thread(target=time.sleep,args=(3,))
  # t.start()
  print('%s is running' %os.getpid())
  time.sleep(2)
  print('%s is done' %os.getpid())
 
if __name__ == '__main__':
  t=Thread(target=task)
  t.daemon = True
  t.start()
  print('主')

輸出如下:

13368 is running
主

原因是:
在執行到守護子線程t,由於主線程子線程通用一塊內存,所以不存在不同進程創建各自空間,所以就先輸出子進程的執行任務代碼,所以輸出print(‘%s is running’ %os.getpid()),由於time.sleep(2),所以就會執行主線程“main”,然後主線程執行完畢,那麼即使2秒過後,由於主線程執行完畢,那麼子守護線程也就退出了,所以 print(‘%s is done’ %os.getpid())就不會執行了

守護子線程非守護子進程並存

我們解析來看一個守護子線程非守護子進程並存的例子

from threading import Thread
import time
def foo():
  print(123)
  time.sleep(1)
  print("end123")
 
def bar():
  print(456)
  time.sleep(3)
  print("end456")
 
if __name__ == '__main__':
  t1=Thread(target=foo)
  t2 = Thread(target=bar)
 
  t1.daemon=True
 
  t2.start()
  t1.start()
  print("main-------")

輸出如下:

456
123
main-------

end123

end456

原因是:
t1是守護子線程,t2非守護子線程,跟主線程使用一塊內存,所以會輸出t1,t1子線程的任務代碼,所以執行456,123由於t1,t2都有睡眠時間,所以執行主線程代碼,然後對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程纔算運行完畢,所以會執行t1,t2睡眠後的任務代碼,然後程序退出。
我們會問爲什麼t1守護子線程,也會執行sleep後的代碼,不是說主線程代碼執行完畢,守護線程就被幹掉了嗎?這裏要注意是對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程纔算運行完畢,當時t2還沒執行完畢
非常感謝你的閱讀
大學的時候選擇了自學python,工作了發現吃了計算機基礎不好的虧,學歷不行這是
沒辦法的事,只能後天彌補,於是在編碼之外開啓了自己的逆襲之路,不斷的學習python核心知識,深入的研習計算機基礎知識,整理好了,如果你也不甘平庸,那就與我一起在編碼之外,不斷成長吧!
其實這裏不僅有技術,更有那些技術之外的東西,比如,如何做一個精緻的程序員,而不是“屌絲”,程序員本身就是高貴的一種存在啊,難道不是嗎?[點擊加入]想做你自己想成爲高尚人,加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章