Python - Ngắt luồng Thread

Xin chào, các nhà lập trình Python mới! Hôm nay, chúng ta sẽ đi mạo hiểm vào một chủ đề thú vị: ngắt luồng threads trong Python. Đừng lo lắng nếu bạn mới bắt đầu học lập trình; tôi sẽ hướng dẫn bạn từng bước trên hành trình này, như thế tôi đã làm cho hàng ngàn học viên trong những năm dạy học. Hãy cùng nhau bắt đầu cuộc phiêu lưu này!

Python - Interrupting a Thread

Thread là gì?

Trước khi bước vào việc ngắt luồng, hãy nhanh chóng tóm tắt lại điều gì là thread. Hãy tưởng tượng bạn đang đọc một cuốn sách (chương trình chính) và đột nhiên nhớ ra cần gọi điện thoại. Bạn đánh dấu trang (tạo một thread), gọi điện thoại và sau đó quay lại cuốn sách. Đó tương tự như cách threads hoạt động trong lập trình – chúng cho phép một chương trình thực hiện nhiều việc cùng một lúc.

Ngắt Luồng Thread

Bây giờ, hãy giả sử bạn đang trên cuộc gọi điện thoại, nhưng quá lâu và bạn muốn quay lại cuốn sách. Bạn nên làm sao để kết thúc cuộc gọi một cách lịch sự? Đó là nơi việc ngắt luồng thread ra đời. Trong Python, chúng ta có một số cách để làm điều này:

  1. Sử dụng một đối tượng Event
  2. Sử dụng một cờ Flag

Hãy khám phá cả hai phương pháp này với một số ví dụ thú vị!

Ngắt Luồng Thread bằng Đối tượng Event

Đối tượng Event tương đương như một cờ có thể được đặt hoặc xóa. Khi cờ được đặt, nó gửi tín hiệu cho luồng để dừng.

Dưới đây là một ví dụ đơn giản:

import threading
import time

def worker(event):
while not event.is_set():
print("Đang làm việc...")
time.sleep(1)
print("Worker: Tôi đã hoàn thành!")

# Tạo một đối tượng sự kiện
stop_event = threading.Event()

# Tạo và bắt đầu luồng
thread = threading.Thread(target=worker, args=(stop_event,))
thread.start()

# Cho phép luồng chạy trong 5 giây
time.sleep(5)

# Đặt sự kiện để gửi tín hiệu cho luồng dừng
stop_event.set()

# Chờ luồng hoàn thành
thread.join()

print("Main: Đã hoàn thành tất cả!")

Hãy phân tích mã này:

  1. Chúng ta nhập các mô-đun cần thiết: threading để làm việc với luồng, và time để thêm các độ trễ.
  2. Chúng ta định nghĩa một hàm worker mà sẽ tiếp tục làm việc cho đến khi sự kiện được đặt.
  3. Chúng ta tạo một đối tượng Event có tên là stop_event.
  4. Chúng ta tạo và bắt đầu một luồng, truyền stop_event vào.
  5. Chúng ta cho phép luồng chạy trong 5 giây bằng cách sử dụng time.sleep(5).
  6. Chúng ta đặt sự kiện bằng cách sử dụng stop_event.set(), nó gửi tín hiệu cho luồng để dừng.
  7. Chúng ta chờ luồng hoàn thành bằng cách sử dụng thread.join().

Khi bạn chạy đoạn mã này, bạn sẽ thấy "Đang làm việc..." được in ra nhiều lần, sau đó là "Worker: Tôi đã hoàn thành!" và cuối cùng là "Main: Đã hoàn thành tất cả!".

Ngắt Luồng Thread bằng Cờ Flag

Một cách khác để ngắt luồng là bằng cách sử dụng một cờ boolean đơn giản. Phương pháp này hơi thủ công nhưng có thể rất hiệu quả.

Dưới đây là một ví dụ:

import threading
import time

def counting_sheep(stop_flag):
count = 0
while not stop_flag[0]:
count += 1
print(f"Đang đếm cừu: {count}")
time.sleep(1)
print(f"Tôi đã đếm được {count} cừu trước khi đi ngủ!")

# Tạo một đối tượng có thể thay đổi để giữ cờ của chúng ta
stop_flag = [False]

# Tạo và bắt đầu luồng
thread = threading.Thread(target=counting_sheep, args=(stop_flag,))
thread.start()

# Cho phép luồng đếm cừu trong 5 giây
time.sleep(5)

# Đặt cờ thành True để dừng luồng
stop_flag[0] = True

# Chờ luồng hoàn thành
thread.join()

print("Main: Ngủ ngon!")

Hãy phân tích mã này:

  1. Chúng ta định nghĩa một hàm counting_sheep mà đếm cho đến khi stop_flag được đặt thành True.
  2. Chúng ta tạo một danh sách stop_flag với một phần tử boolean. Chúng ta sử dụng danh sách vì nó có thể thay đổi, cho phép chúng ta sửa đổi nó từ bên ngoài luồng.
  3. Chúng ta tạo và bắt đầu một luồng, truyền stop_flag vào.
  4. Chúng ta cho phép luồng đếm cừu trong 5 giây.
  5. Chúng ta đặt stop_flag[0] thành True, gửi tín hiệu cho luồng để dừng.
  6. Chúng ta chờ luồng hoàn thành bằng cách sử dụng thread.join().

Khi bạn chạy đoạn mã này, bạn sẽ thấy số cừu tăng lên trong khoảng 5 giây, sau đó là số cuối cùng, và cuối cùng là "Main: Ngủ ngon!".

So sánh các Phương pháp

Hãy so sánh hai phương pháp này:

Phương pháp Ưu điểm Nhược điểm
Đối tượng Event - Tích hợp đồng bộ hóa nội bộ
- Rõ ràng và phù hợp với Python
- Cần truyền đối tượng sự kiện
Cờ - Dễ triển khai
- Không cần đối tượng bổ sung
- Đồng bộ hóa thủ công
- Có thể xảy ra tình trạng cuộc đua

Kết luận

Xin chúc mừng! Bạn đã học được hai cách để ngắt luồng threads trong Python. Phương pháp sử dụng Đối tượng Event thường được ưa chuộng nhất vì tích hợp đồng bộ hóa nội bộ, nhưng phương pháp cờ cũng có thể hữu ích trong các tình huống đơn giản hơn.

Hãy nhớ, giống như kết thúc cuộc gọi điện thoại một cách lịch sự, việc để cho luồng của bạn có cơ hội để dọn dẹp trước khi dừng cũng rất quan trọng. Trong các ứng dụng thực tế, bạn có thể thêm một số mã dọn dẹp trong hàm luồng của bạn để chạy khi nhận được tín hiệu dừng.

Lập trình là một chủ đề cần nhiều thực hành, vì vậy tôi khuyến khích bạn thử nghiệm với các ví dụ này. Hãy thử sửa đổi chúng, có thể thêm nhiều luồng hoặc thay đổi thời gian. Ai biết? Bạn có thể tạo ra một trò chơi thú vị "ngắt người đếm cừu"!

Chúc mãi mãi lập trình vui vẻ, và may luồng của bạn luôn hợp tác!

Credits: Image by storyset