Python - 多線程

你好,未來的 Python 魔法師們!今天,我們將進入 Python 的多線程世界,展開一段激動人心的旅程。如果你是編程新手,也別擔心;我將成為你友善的嚮導,我們將一步步探索這個主題。所以,拿起你的虛擬魔杖(鍵盤),我們一起深入探險吧!

Python - Multithreading

什麼是多線程?

在我們使用 Python 線程施展魔法之前,先來了解多線程究竟是什麼。想象一下,你是一位在忙碌廚房中的廚師。如果你一個人做飯,一次只能做一件事——切菜、然後燒水、然後煎肉。但是,如果你有許多手能同時做不同的工作呢?這基本上就是多線程為我們的程序所做的!

多線程允許程序在單個進程內同時執行多個任務。這就像有許多廚師(線程)在同一個廚房(進程)中合作準備一頓美味的餐點(程序輸出),使其更快、更有效率。

與進程的比較

現在,你可能在想,“但是老師,我聽過進程也。線程和進程有什麼不同?”這是一個很好的問題!讓我們來解析一下:

  1. 資源使用:線程就像共用房間的兄弟姊妹(記憶體空間),而進程則像擁有獨立房屋的鄰居。線程較輕量,並共享資源,因此在某些任務上更有效率。

  2. 通信:線程可以通過共享變量輕鬆交談,但進程需要使用特殊的“電話”(進程間通信)來相互對話。

  3. 開銷:創建和管理線程通常比進程更快,且需要较少的系統資源。

  4. 複雜性:雖然線程可以使你的程序運行得更快,但也引入了複雜性。這就像玩雜技——如果做得好,既有趣又有效率,但如果你不小心,可能會失手!

Python 的線程處理模塊

Python 是一種慷慨的語言,為我們提供了多個用於處理線程的模塊。其中兩個主要的是:

  1. threading:這是用於處理線程的高階接口。它就像友好的巫師助手一樣,為你完成大部分重活。

  2. _thread:這是低階接口。它就像古老的魔法書——強大但需要更多的專業知識才能正確使用。

今天我們的魔法旅程將聚焦於 threading 模塊,因為它對初學者更友好且廣泛使用。

創建新的線程

好的,讓我們施展第一個線程魔法!以下是創建和啟動新線程的方法:

import threading
import time

def print_numbers():
for i in range(5):
time.sleep(1)
print(f"線程 1: {i}")

# 創建一個新的線程
thread1 = threading.Thread(target=print_numbers)

# 啟動線程
thread1.start()

# 主線程繼續執行
for i in range(5):
time.sleep(1)
print(f"主線程: {i}")

# 等待線程1完成
thread1.join()

print("全部完成!")

讓我們來解析這個魔法咒語:

  1. 我們導入 threadingtime 模塊。
  2. 我們定義一個函數 print_numbers(),該函數將由我們的線程執行。
  3. 我們創建一個新的線程對象,指定它應運行的函數。
  4. 我們使用 start() 方法啟動線程。
  5. 主線程繼續執行其自己的循環。
  6. 我們使用 join() 來等待我們的線程完成後再結束程序。

當你運行這個程序時,你會看到來自兩個線程的數字相互交錯,展示了並發執行!

線程同步

現在,想象一下我們的廚師助手試圖同時使用同一把刀——混亂對吧?這就是線程同步的用武之地。我們使用鎖定來確保一次只有一個線程可以訪問共享資源。

以下是示例:

import threading
import time

# 共享資源
counter = 0
lock = threading.Lock()

def increment_counter():
global counter
for _ in range(100000):
lock.acquire()
counter += 1
lock.release()

# 創建兩個線程
thread1 = threading.Thread(target=increment_counter)
thread2 = threading.Thread(target=increment_counter)

# 啟動線程
thread1.start()
thread2.start()

# 等待兩個線程完成
thread1.join()
thread2.join()

print(f"最終計數器值: {counter}")

在這個示例中,我們使用一個鎖來確保一次只有一個線程可以增加計數器的值,防止競態條件。

多線程優先隊列

最後但同樣重要的是,讓我們看一下多線程的一個實際應用——優先隊列。想象一下醫院急診室,病人根據病情的嚴重性而不是只是到達時間來治療。

import threading
import queue
import time
import random

# 創建一個優先隊列
task_queue = queue.PriorityQueue()

def worker():
while True:
priority, task = task_queue.get()
print(f"處理任務: {task} (優先級: {priority})")
time.sleep(random.uniform(0.1, 0.5))  # 模擬工作
task_queue.task_done()

# 創建並啟動工作線程
for _ in range(3):
thread = threading.Thread(target=worker, daemon=True)
thread.start()

# 將任務添加到隊列中
for i in range(10):
priority = random.randint(1, 5)
task = f"任務 {i}"
task_queue.put((priority, task))

# 等待所有任務完成
task_queue.join()
print("所有任務完成!")

這個示例演示了多個線程如何有效地合作處理優先隊列中的任務。

結論

恭喜你,年輕的 Python 魔法師們!你們剛剛走出了多線程魔法領域的第一步。請記住,能力越大,責任越大——明智地使用線程,它們將使你的程序更快、更有效率。

以下是我們今天涵蓋的主要線程方法的快速參考表:

方法 描述
Thread(target=function) 創建一個新的線程來運行指定的函數
start() 開始線程的活動
join() 等待線程完成
Lock() 創建線程同步的鎖
acquire() 獲取鎖
release() 釋放鎖

繼續練習,保持好奇心,你將能夠像真正的 Python 大師一樣指揮線程!祝編程愉快!

Credits: Image by storyset