Python 執行緒(Threading)

若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

什麼是執行緒?

在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」。

沒有留言: