14. 執行緒

(1) 建立一個執行緒

程式的執行有一個主執行緒. 在主執行緒建立另一個執行緒並啟動它, 整個程式因此有2個執行緒"同時"執行. 所謂的"同時", 是大家分享CPU時間, 交錯執行.

import threading
import time

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function():
    print("開始執行緒")
    for i in range(10):
        print(i)
        time.sleep(1)  #暫停1秒
    print("結束執行緒")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread = threading.Thread(target=my_function)

# 啟動執行緒
my_thread.start()

# 等待執行緒完成
my_thread.join()

print("<<主執行緒完成>>")

執行結果:

<<主執行緒開始>>
開始執行緒
0
1
2
3
4
5
6
7
8
9
結束執行緒
<<主執行緒完成>>

(2) 多個執行緒之間有自己的區域變數

執行緒函式內的變數是由每個執行緒維持自己的一份, 與其他執行緒不互相影響.

import threading
import time

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function():
    print("開始執行緒")
    for i in range(10):
        print(i)
        time.sleep(1)  #暫停1秒
    print(f"結束執行緒")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread1 = threading.Thread(target=my_function)
my_thread2 = threading.Thread(target=my_function)

# 啟動執行緒
my_thread1.start()
my_thread2.start()

# 等待執行緒完成
my_thread1.join()
my_thread2.join()

print("<<主執行緒完成>>")

執行結果:

<<主執行緒開始>>
開始執行緒
0
開始執行緒
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
結束執行緒
結束執行緒
<<主執行緒完成>>

(3) 傳參數給執行緒

import threading
import time

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function(name):
    print(f"開始執行緒{name}")
    for i in range(10):
        print(f'{name}:{i}')
        time.sleep(1)  #暫停1秒
    print(f"結束執行緒{name}")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread1 = threading.Thread(target=my_function, args=('Tom',))
my_thread2 = threading.Thread(target=my_function, args=('Mary',))

# 啟動執行緒
my_thread1.start()
my_thread2.start()

# 等待執行緒完成
my_thread1.join()
my_thread2.join()

print("<<主執行緒完成>>")

執行結果:

<<主執行緒開始>>
開始執行緒Tom
Tom:0
開始執行緒Mary
Mary:0
Tom:1
Mary:1
Tom:2
Mary:2
Mary:3
Tom:3
Tom:4
Mary:4
Tom:5
Mary:5
Tom:6
Mary:6
Tom:7
Mary:7
Tom:8
Mary:8
Tom:9
Mary:9
結束執行緒Tom
結束執行緒Mary
<<主執行緒完成>>

(4) 執行緒之間共用廣域變數

import threading
import time

# 建立一個鎖
lock = threading.Lock()

# 廣域變數
counter=0

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function(name):
    global counter
    print(f"開始執行緒{name}")
    for i in range(10):
        with lock:
            counter+=1
            print(f'{name}:{counter}')
        time.sleep(1)  #暫停1秒
    print(f"結束執行緒{name}")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread1 = threading.Thread(target=my_function, args=('Tom',))
my_thread2 = threading.Thread(target=my_function, args=('Mary',))

# 啟動執行緒
my_thread1.start()
my_thread2.start()

# 等待執行緒完成
my_thread1.join()
my_thread2.join()

print("<<主執行緒完成>>")

執行結果:

<<主執行緒開始>>
開始執行緒Tom
Tom:1
開始執行緒Mary
Mary:2
Tom:3
Mary:4
Mary:5
Tom:6
Mary:7
Tom:8
Tom:9
Mary:10
Mary:11
Tom:12
Mary:13
Tom:14
Tom:15
Mary:16
Mary:17
Tom:18
Mary:19
Tom:20
結束執行緒Mary
結束執行緒Tom
<<主執行緒完成>>

(5) 執行緒與閉包

import threading
import time
import random

#--------------------------
# 取得counter()物件的位址
#--------------------------
def make_counter():
    cnt=0
    def counter():
        nonlocal cnt
        cnt+=1
        return cnt
    
    return counter

#--------------------------
# 執行緒內容的函式
#--------------------------
def my_function(name, counter):
    for i in range(10):
        print(f'{name}->{counter()}')
        time.sleep(random.randint(1,2))

#------------------
# 產生一個閉包
#------------------
counter=make_counter()
        
#------------------
# 產生2個執行緒
#------------------       
my_thread1 = threading.Thread(target=my_function, args=('tom', counter))
my_thread2 = threading.Thread(target=my_function, args=('mary', counter))

#------------------
# 啟動執行緒
#------------------ 
my_thread1.start()  
my_thread2.start()        

執行結果:

tom->1
mary->2
tom->3
mary->4
tom->5
mary->6
mary->7
tom->8
mary->9
tom->10
tom->11
mary->12
mary->13
tom->14
tom->15
mary->16
tom->17
mary->18
tom->19
mary->20

Last updated