一個專題很常需要同時對多個輸入輸出做動作。這個問題第一眼看到時可能覺得還好,因為電腦執行速度很快,即使稍微慢一點點也看不出來──但萬一我們的很多動作都需要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本身資源,則使用多線程就足矣。