一個專題很常需要同時對多個輸入輸出做動作。這個問題第一眼看到時可能覺得還好,因為電腦執行速度很快,即使稍微慢一點點也看不出來──但萬一我們的很多動作都需要time.sleep函式來控制,比方說,連接7個LED,各自用不同頻率閃爍。 像這類問題一個解法是自己計算時間順序: ```python time_count = 0 while 1: if time_count%需求秒數1 == 0: GPIO.output(LED1,1) if time_count%需求秒數2 == 0: …… time.sleep(0.1) time_count = 0 if time_count>上限 else time_count + 1 ``` 透過把時間軸細化的方式達成擬似的功能,但隨著時間過去,誤差會越來越大,尤其是包在裡面的東西需要的運算量越多,這狀況會越明顯。(就是所謂的執行時間) 事實上,python對於多核心的處理有完善的支援。在開始講解這部分之前我們先解釋一下多工的兩個分類──多線程和多進程。 ### 多線程 多線程嚴格來說並不能解決我們上面的問題,他是將許多的執行程序塞在同一個核心裏面,依照切換的方式讓我們以為程式是同步執行的。 在python裡面我們可以使用threading這個函式庫來實做這件事情: ```python import threading import time def thread_1(): for i in range(4): print('This is a thread 1_' + str(i)) time.sleep(.5) def thread_2(): for i in range(4): print('This is a thread 2_' + str(i)) time.sleep(.5) thread = threading.Thread(target=thread_1,) thread.start() thread2 = threading.Thread(target=thread_2,) thread2.start() ------------------------------------------ This is a thread 1_0 This is a thread 2_0 This is a thread 1_1 This is a thread 2_1 This is a thread 1_2 This is a thread 2_2 This is a thread 1_3 This is a thread 2_3 ``` 所有需要使用多執行緒的部分都必須用一個子程式包起來,並且使用threading底下的thread方法,告訴它要分出去執行的目標是哪個子程式,以及子程式需要(如果有)的參數。 ### 多進程 多進程和多線程程式撰寫方法類似,但它是將工作分派給不同核心: ```python import multiprocessing as mp import time def thread_1(): for i in range(10): print('This is a thread 1_' + str(i)) time.sleep(.5) def thread_2(): for i in range(10): print('This is a thread 2_' + str(i)) time.sleep(.5) if __name__=='__main__': thread = mp.Process(target=thread_1,) thread2 = mp.Process(target=thread_2,) thread.start() thread2.start() ``` 至於什麼時候該選擇哪一個呢? 可以利用準備執行的程式是不是高運算程式當成一個標準。一般而言,當任務本身是很多運算量很高,尤其是需要頻繁讀取硬碟或IO的東西的時候,使用多進程可以利用更多核心進行運算,因此效率會比較好。 而如果任務本身是很多需要等待的任務--例如爬蟲這類都在等網站回傳訊息的任務,或是像UI這種等待使用者操作的任務。這種狀況不太吃CPU本身資源,則使用多線程就足矣。