你真的了解線程的基礎(chǔ)知識嗎?這些技巧讓你的代碼更高效!
當(dāng)涉及到多任務(wù)處理時(shí),線程是一種非常實(shí)用的技術(shù)。Python語言提供了內(nèi)置的線程支持庫,使得創(chuàng)建和管理線程變得非常容易。本文將深入介紹Python中的線程概念,線程創(chuàng)建和管理,線程狀態(tài)和生命周期,線程的屬性和方法以及線程的調(diào)度和優(yōu)先級。
線程概念和基本原理
線程是進(jìn)程中的執(zhí)行單元,每個(gè)線程都有自己的執(zhí)行路徑和執(zhí)行狀態(tài)。一個(gè)進(jìn)程可以包含多個(gè)線程,每個(gè)線程都可以同時(shí)執(zhí)行不同的任務(wù)。線程是輕量級的,開銷小,執(zhí)行效率高,因此在高并發(fā)和多任務(wù)處理場景中得到廣泛應(yīng)用。
在Python中,線程是通過threading模塊實(shí)現(xiàn)的。創(chuàng)建線程可以使用Thread類或繼承Thread類自定義線程。線程的創(chuàng)建和啟動可以使用start()方法。
import threading
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_numbers)
# 啟動線程
t1.start()
t2.start()
上面代碼中,我們創(chuàng)建了兩個(gè)線程t1和t2,用于執(zhí)行print_numbers函數(shù)。通過start()方法啟動線程后,兩個(gè)線程會同時(shí)執(zhí)行print_numbers函數(shù)。
線程的狀態(tài)和生命周期
線程在運(yùn)行過程中會出現(xiàn)不同的狀態(tài),包括新建狀態(tài)、就緒狀態(tài)、運(yùn)行狀態(tài)、阻塞狀態(tài)和終止?fàn)顟B(tài)。線程的狀態(tài)可以通過is_alive()方法查詢。
線程的生命周期包括線程創(chuàng)建、線程就緒、線程運(yùn)行、線程阻塞和線程終止。線程的生命周期可以通過join()方法控制。
import threading
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_numbers)
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
print("All threads have finished")
上面代碼中,我們使用join()方法等待線程t1和t2執(zhí)行完畢后才輸出"All threads have finished"。這種等待方式可以保證主線程在所有子線程執(zhí)行完畢后再退出。
線程的屬性和方法
Python中的線程有很多屬性和方法,可以讓我們更加靈活地控制線程的執(zhí)行。下面將詳細(xì)講解線程的屬性和方法,以及每個(gè)方法的作用和代碼示例。
線程屬性
name屬性
name屬性用于獲取或設(shè)置線程的名稱。線程的名稱可以是任意字符串。
import threading
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
# 創(chuàng)建線程并設(shè)置名稱
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 獲取線程名稱
print(t1.name)
print(t2.name)
# 啟動線程
t1.start()
t2.start()
daemon屬性
daemon屬性用于設(shè)置線程是否為守護(hù)線程。守護(hù)線程是一種特殊的線程,當(dāng)所有非守護(hù)線程執(zhí)行完畢后,守護(hù)線程自動退出。
import threading
import time
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
time.sleep(0.5)
# 創(chuàng)建線程并設(shè)置為守護(hù)線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2", daemon=True)
# 獲取線程守護(hù)狀態(tài)
print(t1.daemon)
print(t2.daemon)
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
print("All threads have finished")
ident屬性
ident屬性用于獲取線程的標(biāo)識符。線程的標(biāo)識符是一個(gè)整數(shù),唯一標(biāo)識該線程。
import threading
# 線程函數(shù)
def print_ident():
print(threading.current_thread().name, ":", threading.current_thread().ident)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_ident, name="Thread 1")
t2 = threading.Thread(target=print_ident, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
is_alive()方法
is_alive()方法用于判斷線程是否在運(yùn)行。
import threading
import time
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
time.sleep(0.5)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
# 判斷線程是否在運(yùn)行
print(t1.is_alive())
print(t2.is_alive())
線程方法
start()方法
start()方法用于啟動線程。一旦線程啟動,它將執(zhí)行target指定的函數(shù)。
import threading
import time
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
time.sleep(0.5)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
join()方法
join()方法用于等待線程執(zhí)行完畢。如果不使用join()方法,主線程將在子線程之前結(jié)束,導(dǎo)致子線程被強(qiáng)制結(jié)束。
import threading
import time
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
time.sleep(0.5)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
print("All threads have finished")
run()方法
run()方法是線程執(zhí)行時(shí)調(diào)用的方法。默認(rèn)情況下,run()方法調(diào)用target指定的函數(shù)。
import threading
import time
# 線程類
class MyThread(threading.Thread):
def run(self):
for i in range(10):
print(self.name, ":", i)
time.sleep(0.5)
# 創(chuàng)建線程
t1 = MyThread(name="Thread 1")
t2 = MyThread(name="Thread 2")
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
print("All threads have finished")
sleep()方法
sleep()方法用于將線程休眠一段時(shí)間。在休眠期間,線程不會執(zhí)行任何操作。
import threading
import time
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
time.sleep(0.5)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
# 休眠線程
time.sleep(1)
print("All threads have finished")
enumerate()方法
enumerate()方法用于返回當(dāng)前正在運(yùn)行的所有線程。
import threading
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
# 獲取所有正在運(yùn)行的線程
for thread in threading.enumerate():
print(thread.name)
active_count()方法
active_count()方法用于返回當(dāng)前正在運(yùn)行的線程數(shù)。
import threading
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 啟動線程
t1.start()
t2.start()
# 獲取正在運(yùn)行的線程數(shù)
print(threading.active_count())
線程的調(diào)度和優(yōu)先級
線程調(diào)度是指多個(gè)線程之間的競爭和協(xié)作機(jī)制,通過優(yōu)先級和時(shí)間片輪轉(zhuǎn)等方式來調(diào)度線程的執(zhí)行。Python中可以通過threading模塊的setpriority()方法設(shè)置線程的優(yōu)先級。線程的優(yōu)先級可以是整數(shù),范圍為0到sys.maxsize。
在Python中,線程的優(yōu)先級僅僅是一個(gè)建議,具體的線程調(diào)度由操作系統(tǒng)來完成。
import threading
# 線程函數(shù)
def print_numbers():
for i in range(10):
print(threading.current_thread().name, ":", i)
# 創(chuàng)建線程
t1 = threading.Thread(target=print_numbers, name="Thread 1")
t2 = threading.Thread(target=print_numbers, name="Thread 2")
# 設(shè)置線程優(yōu)先級
t1.setpriority(1)
t2.setpriority(2)
# 啟動線程
t1.start()
t2.start()
# 等待線程結(jié)束
t1.join()
t2.join()
print("All threads have finished")
上面代碼中,我們使用setpriority()方法設(shè)置線程的優(yōu)先級,t1的優(yōu)先級為1,t2的優(yōu)先級為2。線程的優(yōu)先級越高,在競爭CPU資源時(shí)就越有可能被調(diào)度執(zhí)行。
總結(jié)
本文介紹了Python中線程的基礎(chǔ)知識,包括線程概念和基本原理,線程的創(chuàng)建和管理,線程狀態(tài)和生命周期,線程的屬性和方法以及線程的調(diào)度和優(yōu)先級。如果您需要在Python中進(jìn)行多任務(wù)處理,線程將是一個(gè)非常實(shí)用的技術(shù),可以提高程序的效率和性能。