進程和併發

咱們已經講過了什麼是線程,那今天就來學習一下什麼是進程,**進程(Process)**是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操做系統結構的基礎。 進程是正在運行的程序的實例,簡單的說就是好比咱們本身在python文件中寫了一些代碼,這叫作程序,而運行這個python文件的時候就叫作進程html

什麼是併發

那什麼是併發呢,併發就是在某個時間段內,兩件或兩件以上的事件輪流交替使用某一資源,其目的是提升效率; 須要注意的是併發和並行的區別:python

  • 併發是指兩個或多個事件在同一時間間隔發生,並行是指兩個或者多個事件在同一時刻發生;
  • 併發是在同一實體上的多個事件,並行是在不一樣實體上的多個事件;

multiprocess模塊

Python中提供multiprocess模塊實現多進程併發,咱們來看一下multiprocess模塊的使用,經過一個實例來對比多線程和多進程程序運行對CPU的使用狀況linux

import multiprocessing
import threading

def worker():
    number = 0
    for i in range(10000000):
        number += 1
        print('循環次數:{} number:{}'.format(i+1, number))

if __name__ == '__main__':
    for i in range(4):
        # 建立線程
        threading.Thread(target=worker, name='thread worker {}'.format(i)).start()

        # 建立進程
        multiprocessing.Process(target=worker, name='process worker {}'.format(i)).start()

分別啓動線程和進程,運行代碼,查看電腦的CPU的使用率,發現多進程佔用內存多,切換複雜,CPU利用率低,多線程佔用內存少,切換簡單,CPU利用率高;多線程

進程的一些對象方法併發

import multiprocessing
import threading
import time

def worker():
    number = 0
    for i in range(10000000):
        number += 1
        time.sleep(0.1)
        print(multiprocessing.current_process().name)  # 獲取當前進程的名稱
        print('循環次數:{} number:{}'.format(i+1,number ))
        
if __name__ == '__main__':
    for i in range(4):
        process = multiprocessing.Process(target=worker, name='process worker {}'.format(i))
        process.start()
        print(process.pid) # 獲取進程的pid
        print(process.exitcode) # 獲取退出狀態碼
        print(process.name)  # 獲取進程名稱
        time.sleep(30)
        print(process.terminate()) # 終止進程
  • multiprocessing支持子進程、通訊和共享數據、執行不一樣形式的同步,提供了ProcessQueuePipeLock等 組件;函數

  • 可使用multiprocessing.Process對象來建立一個進程,該進程能夠運行在Python程序內部編寫的函數;學習

  • process模塊是一個建立進程的模塊,藉助這個模塊,就能夠完成進程的建立,有start()run()join()的方法;fetch

進程併發:concurrent模塊

from concurrent.futures import ProcessPoolExecutor
import requests

def fetch_url(url):
    result = requests.get(url=url, )
    return result.text
if __name__ == '__main__':
    # 建立10個線程隊列的線程池
    pool = ProcessPoolExecutor(10)
    # 獲取任務返回對象
    a = pool.submit(fetch_url, 'http://www.baidu.com')
    # 取出返回的結果
    x = a.result()
    print(x)

也可使用上下文管理的方式url

from concurrent.futures import ProcessPoolExecutor
import requests

def fetch_url(url):
    result = requests.get(url=url, )
    return result.text
if __name__ == '__main__':
    with ProcessPoolExecutor(max_workers=10) as pool:
        a = pool.submit(fetch_url, 'http://www.9xkd.com')
        print(a.result())
  • concurrent模塊可以提供一個future的實例對象,實例對象提供了線程的執行器和進程的執行器;操作系統

  • submit():返回一個Future對象;

  • result():查看調用的返回結果;

  • done():若是任務成功執行或任務取消返回True;

  • cancel():取消任務;

  • running():若是任務正在執行返回True;

  • exception(): 獲取執行拋出的異常;

守護進程實現(POSIX兼容)

  • 在linux或者unix操做系統中,守護進程(Daemon)是一種運行在後臺的特殊進程,它獨立於控制終端而且週期 性的執行某種任務或等待處理某些發生的事件;

  • 因爲在linux中,每一個系統與用戶進行交流的界面稱爲終端,每個今後終端開始運行的進程都會依附於這個終 端,這個終端被稱爲這些進程的控制終端,當控制終端被關閉的時候,相應的進程都會自動關閉;

  • 可是守護進程卻能突破這種限制,它脫離於終端而且在後臺運行,而且它脫離終端的目的是爲了不進程在運 行的過程當中的信息在任何終端中顯示而且進程也不會被任何終端所產生的終端信息所打斷,它從被執行的時候 開始運轉,直到整個系統關閉才退出;

守護進程實現的步驟:

  • 父進程fork出子進程並exit退出;

  • 子進程調用setsid建立新會話;

  • 子進程調用系統函數chdir將根目錄"/"成爲子進程的工做目錄;

  • 子進程調用系統函數umask將該進程的umask設置爲0;

  • 子進程關閉從父進程繼承的全部不須要的文件描述符;

對 os.fork( )的理解:

  • os.fork()返回兩個值,一個是在當前父進程返回的,一個是在子進程中返回的;

  • 子進程返回的是0,父進程返回的是子進程的pid;

import os
pid = os.fork()
print(pid)
if pid == 0:
    print("我是子進程 pid={}, parent_pid={}".format(os.getpid(), os.getppid()))
else:
    print("我是父進程 pid={}, parent_pid={}".format(os.getpid(), os.getppid()))

參考:https://www.9xkd.com/user/plan-view.html?id=1923439230

相關文章
相關標籤/搜索