Python入門進階教程-多線程與多進程

在這裏插入圖片描述

「關注我,和我一起放下靈魂,讓靈魂去搬磚。」

Python多線程與多進

Python版本3.8.0,開發工具:Pycharm

試想一下當你有1w個小文件需要處理,假設每個文件讀取處理到寫入需要1秒,

那麼你處理完所以文件會需要兩個多小時。

但是如果你可以同時開啓四個任務處理1w 個文件,每個任務平均處理2500個

這個時候你的時間可以壓縮在一小時以內。

如何同時對一個文件夾開啓四個任務同時處理不同的任務,而不會產生衝突,接下來我們一起了解一下多線程和多進程。

進程與線程

從一定意義上講,進程就是一個應用程序在處理機上的一次執行過程,它是一個動態的概念,而線程是進程中的一部分,進程包含多個線程在運行。

進程是資源(CPU、內存等)分配的基本單位,它是程序執行時的一個實例。線程是程序執行時的最小單位,它是進程的一個執行流,是CPU調度和分派的基本單位,一個進程可以由很多個線程組成,線程間共享進程的所有資源。

Python多線程

Python 中提供兩個標準庫 thread 和 threading 用於對線程的支持,但 Python3 中已放棄對 thread 的支持,所以接下來均以 threading 爲例。

python中有兩種方式實現線程:

  • 1.實例化一個 threading.Thread 的對象,並傳入一個初始化函數對象作爲線程執行的入口;
  • 2.繼承 threading.Thread,並重寫 run 函數;
# 第一種實現線程的方法
import threading
# my_fun爲自定義函數,args爲自定義函數的參數
thread1 = threading.Thread(target=my_fun, args=('This is thread 1',))
thread2 = threading.Thread(target=my_fun, args=('This is thread 2',))
# 啓動線程
thread1.start()
thread2.start()


# 第二中實現線程的方法
class MyThread(threading.Thread):
    # step 1: call base __init__ function
    def __init__(self, thread_name):
        super(CustomThread, self).__init__(name=thread_name)
        self._tname = thread_name
    # step 2: overide run function
    def run(self):
        print("This is %s running...." % self._tname)
# 實例化MyThread
thread1 = MyThread("thread 1")
thread2 = MyThread("thread 2")
# 啓動線程
thread1.start()
thread2.start()

注:

  • 兩種方式創建線程,指定的參數最終都會傳給threading.Thread類;
  • 傳給線程的目標函數是在基類Thread的run函數體中被調用的,如果run沒有被重寫的話。

threading.Thread提供的線程對象方法和屬性:

1. start():創建線程後通過start啓動線程,等待CPU調度,爲run函數執行做準備;
2. run():線程開始執行的入口函數,函數體中會調用用戶編寫的target函數,或者執行被重載的run函數;
3. join([timeout]):阻塞掛起調用該函數的線程,直到被調用線程執行完成或超時。通常會在主線程中調用該方法,等待其他線程執行完成。
4. name、getName()&setName():線程名稱相關的操作;
5. ident:整數類型的線程標識符,線程開始執行前(調用start之前)爲None;
6. isAlive()、is_alive():start函數執行之後到run函數執行完之前都爲True;
7. daemon、isDaemon()&setDaemon():守護線程相關。

Python多進程

Python 提供 multiprocessing 用於創建多進程

創建進程的方式和創建線程的方式類似:

  • 1.實例化一個 multiprocessing.Process 的對象,並傳入一個初始化函數對象作爲新建進程執行入口;
  • 2.繼承 multiprocessing.Process,並重寫 run 函數;
# 第一種實現進程的方法
from multiprocessing import Process

# my_fun爲自定義函數,args爲自定義函數的參數
process1 = Process(target=my_fun, args=('This is process 1',))
process2 = Process(target=my_fun, args=('This is process 2',))
# 啓動線程
process1.start()
process2.start()
# join()方法可以等待子進程結束後再繼續往下運行,通常用於進程間的同步。
process1.join()
process2.join()


# 第二中實現進程的方法
from multiprocessing import Process  

class MyProcess(Process):
    def __init__(self, p_name, target=None):
        # step 1: call base __init__ function()
        super().__init__(name=p_name, target=target, args=(p_name,))

    def run(self):
        # step 2:
        print("Process name: %s, pid: %s " % (self.name, os.getpid()))

if __name__ == '__main__':
    # 實例化MyProcess
    process1 = MyProcess("process 1")
    process2 = MyProcess("process 2")
    # 啓動進程
    process1.start()
    process2.start()
    process1.join()
    process2.join()


進程 vs. 線程

是否採用多任務需要考慮任務的類型,我們可以把任務分爲CPU密集型和IO密集型。

  • CPU密集型任務的特點是要進行大量的計算,消耗CPU資源,比如計算圓周率、對視頻進行高清解碼等等,全靠CPU的運算能力。
  • 涉及到網絡、磁盤IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成

總結:

  • CPU密集型:程序需要佔用CPU進行大量的運算和數據處理;
  • I/O密集型:程序中需要頻繁的進行I/O操作;例如網絡中socket數據傳輸和讀取等;

由於python多線程並不是並行執行,因此較適合與I/O密集型程序,多進程並行執行適用於CPU密集型程序;


根據任務的需求選擇相應的多任務方式,在多文件數據操作、爬蟲等任務時相當實用!


下節將介紹Python JSON操作

系列文章傳送門

Python入門進階教程-正則表達式

Python入門進階教程-面向對象

Python入門基礎彙總


Python系列

Python系列會持續更新,從基礎入門到進階技巧,從編程語法到項目實戰。若您在閱讀的過程中發現文章存在錯誤,煩請指正,非常感謝;若您在閱讀的過程中能有所收穫,歡迎一起分享交流。

如果你也想和我一起學習Python,可以關注我的微信公衆號

學習Python,我們不只是說說而已

在這裏插入圖片描述

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