什麼是執行緒?
在Windows系統裡,可以從工作管理員(taskmgr)看到程序(process):而這些程序是在作業系統裡執行中的程式,且在ram上有自己的記憶體空間,從上圖可以知道電腦裡有很多的程序在同一時間運行。而執行緒(thread)是附屬於程序的,一個程序可以擁有很多個執行緒,例如上圖中的Google Chrome可能有20個執行緒在運行中。現在的CPU有多個核心(Core)數,每一個程序會被作業系統分配到各自的 CPU Core裡。CPU Core、RAM、Process、Thread的關係如下圖:
以上圖中的 Process 1 為例,它被分配到 Core 1,有 RAM 1的記憶體空間,擁有 Thread A, B兩個執行緒。從上圖來看,執行緒好像可以同時運行,但,它只是看起來很像在同時執行,除此之外還有些其他議題需要考慮的。
執行緒的建立與執行
Python建立執行緒的方式有兩種:1. 呼叫_thread.start_new_thread ( function, args[, kwargs] )函數(https://docs.python.org/3/library/_thread.html)。
程式範例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import _thread import time t = 0 # 執行緒所用的輸出系統時間之函數 def prt_time( threadID, interval): cnt = 0 while cnt < 3: time.sleep(interval) cnt += 1 print( "%s 現在時間:%s" % ( threadID, time.ctime(time.time()) ) ) # 建立兩個執行緒 try: _thread.start_new_thread( prt_time, ("執行緒A", 1, ) ) _thread.start_new_thread( prt_time, ("執行緒B", 3, ) ) except: print( "錯誤: 執行緒無法執行") while t <= 10: time.sleep(1.5) print("主執行緒 現在時間:%s" % ( time.ctime(time.time()) ) ) t = t + 1 print("主執行緒結束") |
範例程式結果:
2. 繼承 Thread 類別。
範例程式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import threading import time t = 0 class myThread (threading.Thread): def __init__(self, threadID, delay): threading.Thread.__init__(self) self.id = threadID self.delay = delay def run(self): print ("執行 " + self.id) prt_time(self.id, self.delay) print ("離開 " + self.id) # 執行緒所用的輸出系統時間之函數 def prt_time( threadID, delay): cnt = 0 while cnt < 3: time.sleep(delay) cnt += 1 print( "%s 現在時間:%s" % ( threadID, time.ctime(time.time()) ) ) # 建立兩個執行緒 thread1 = myThread("執行緒A", 1) thread2 = myThread("執行緒B", 3) # 啟動執行緒 thread1.start() thread2.start() # 等待執行緒結束 thread1.join() thread2.join() print ("離開主執行緒") |
範例程式結果:
執行緒同步化
有時執行緒必須等待另一個執行緒結束才能執行。這時可以使用 lock 的機制。範例程式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import threading import time t = 0 lock = threading.Lock() class myThread (threading.Thread): def __init__(self, threadID, delay): threading.Thread.__init__(self) self.id = threadID self.delay = delay def run(self): print ("執行 " + self.id) lock.acquire() prt_time(self.id, self.delay) lock.release() print ("離開 " + self.id) # 執行緒所用的輸出系統時間之函數 def prt_time( threadID, delay): cnt = 0 while cnt < 3: time.sleep(delay) cnt += 1 print( "%s 現在時間:%s" % ( threadID, time.ctime(time.time()) ) ) # 建立兩個執行緒 thread1 = myThread("執行緒A", 1) thread2 = myThread("執行緒B", 3) # 啟動執行緒 thread1.start() thread2.start() # 等待執行緒結束 thread1.join() thread2.join() print ("離開主執行緒") |
範例程式結果:
以上介紹了 Python Threading 的基本用法,以及同步的作法。此外同步化有個經典的範例,有興趣的讀者可參考這篇文章:「Producer-Consumer Threading」。
沒有留言:
張貼留言