2021年11月16日 星期二

[Python] Threading (2):Hello Thread 建立第一個 Multithread 程式


承接上一章,我們大概了解了 Python Multithreading 的一點概念,接下來就是實際實作。

基本上在 Python 實作 multithread 程式一定會用到 Python 內建的 threading 模組
threading module 官方文件:https://docs.python.org/zh-tw/3/library/threading.html


1. 在 python 程式裡如何建立thread?


起首式,首要做的是 import threading 模組
再來就是建立 threading.Thread 物件

最關鍵的是我們要怎麼初始化這個 Thread 物件,看看文件:

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)


這裡大概比較需要知道與設定的有兩個參數:

- target:傳入想要執行的function

- args:帶入想要傳到function的參數,比較要注意的是要寫成tuple型式來傳入,另外如果只想傳一個參數寫成這樣是不行的(x),要寫成這樣(x,)才會被視作tuple


範例:


import threading

def hello(x):
    print(f"Number: {x}")

workers = []
for i in range(3):
    t = threading.Thread(target = hello, args=(i,))
    t.start()
    workers.append(t)

for i in range(3):
    workers[i].join()

print(workers[0].is_alive())  # False
print("End")



上面的範例程式是跑了三個thread,並執行hello這個函式,分別傳入 1,2,3 的值到 hello 函式裡


2. start() 與 join()


start() 與 join() 是 Thread 物件的方法函式

- start():呼叫start()後,thread才會開始執行target function

- join(timeout=None):跑到 join() 時當前程式會阻塞,直到該thread跑完target function,才執行下一段程式碼,多用在我們要確保某thread確實執行完target function時
同一個thread可以被join()多次
可以設定timeout時間,預設None指的是沒有timeout,會等到thread結束

其他可能還會需要知道的 thread 物件方法:

- is_alive() :return bool,可以用來確認這thread是否已經結束



3. Thread 物件包裝的寫法


我們試著將上面的範例改寫成物件導向的形式

將要做的事包裝成一個我們自建的 Worker class
整體的程式碼閱讀起來也比較好懂


import threading

class Worker(threading.Thread):
    def __init__(self, x):
        super().__init__()
        self.num = x
 
    def run(self):
        print(f"Number: {self.num}")

workers = []
for i in range(3):
    w = Worker(i)
    w.start()
    workers.append(w)

for i in range(3):
    workers[i].join()


Worker 繼承 threading.Thread 特性與方法,然後覆寫 run() 函式,寫入我們要讓thread執行的程式碼
其實 call start() 就是會生成 thread 跑 run() 函式,預設是會跑 target 參數傳入的 函式


上一章:[Python] Multithreading (1):什麼是多執行緒 Multithreading

下一章:[Python] Multithreading (3):Race Condition 與 Thread-Safe 



沒有留言:

張貼留言