Trong Python, daemon threads là các thread chạy ở nền và tự động kết thúc khi thread chính kết thúc. Trong khi các thread thông thường (non-daemon threads) sẽ không cho phép chương trình kết thúc cho đến khi tất cả các thread kết thúc, daemon threads được thiết kế để phục vụ các tác vụ nền như cập nhật dữ liệu, theo dõi trạng thái hoặc phân tích dữ liệu.
Cú pháp khai báo một daemon thread như sau:
thread_name = threading.Thread(target=function_name, args=(arg1, arg2, ...))
thread_name.daemon = True
Trong đó target
là tên của hàm sẽ được thực thi trong thread, args
là danh sách các tham số truyền vào hàm, thread_name
là tên của thread (tuỳ chọn), và daemon
được thiết lập bằng True
để đánh dấu thread là daemon thread.
Lưu ý rằng nếu tất cả các thread còn lại trong chương trình đều là daemon threads, thì chương trình sẽ kết thúc ngay lập tức mà không cần chờ đợi các daemon threads hoàn thành.
Ví dụ 1:
import threading
import time
def task():
print("Starting task...")
time.sleep(5)
print("Task finished.")
# Tạo một daemon thread
thread = threading.Thread(target=task)
thread.daemon = True
thread.start()
# Chờ 1 giây để thread hoạt động
time.sleep(1)
print("Main thread finished
Kết quả:
Starting task…
Main thread finished
Ở ví dụ trên, chương trình chỉ chờ 1 giây để cho thread hoạt động. Sau đó, thread chạy trong 5 giây nhưng vì nó là daemon thread nên chương trình kết thúc ngay lập tức mà không cần chờ đợi thread hoàn thành.
Ví dụ 2:
Giả sử bạn đang viết một ứng dụng đa luồng để xử lý các tác vụ đồng thời. Trong ứng dụng của bạn, bạn cần một luồng để theo dõi dữ liệu từ các cảm biến và lưu nó vào file. Tuy nhiên, nếu quá trình xử lý dữ liệu này bị gián đoạn hoặc bị ngưng, bạn không muốn ứng dụng của bạn bị treo. Thay vào đó, bạn muốn luồng này chạy ở chế độ nền và tự động thoát khi ứng dụng của bạn kết thúc.
Bạn có thể sử dụng daemon threads để làm việc này. Khi một luồng được đánh dấu là daemon thread, nó sẽ tự động kết thúc nếu tất cả các luồng khác đã kết thúc và ứng dụng của bạn sẽ không bị treo.
Dưới đây là một ví dụ về cách sử dụng daemon thread trong Python:
import threading
import time
def worker():
print("Worker started")
time.sleep(2)
print("Worker finished")
t = threading.Thread(target=worker, daemon=True)
t.start()
print("Main thread exiting")
Trong ví dụ này, chúng ta tạo một luồng t
và đánh dấu nó là daemon thread bằng cách thiết lập tham số daemon=True
. Luồng t
chỉ đơn giản là in ra thông báo “Worker started”, đợi 2 giây, sau đó in ra thông báo “Worker finished”. Sau đó, chúng ta bắt đầu chạy luồng t
và in ra thông báo “Main thread exiting”. Vì luồng t
là daemon thread, nó sẽ tự động kết thúc khi ứng dụng chính của chúng ta kết thúc.
Ví dụ 3:
Giả sử bạn muốn tạo một daemon thread trong Python để theo dõi việc thực thi của một ứng dụng và ghi lại thông tin về tình trạng của ứng dụng. Để làm điều này, bạn có thể sử dụng module logging
để ghi lại các thông tin về tình trạng của ứng dụng và sử dụng một daemon thread để theo dõi và ghi lại các thông tin này.
Ví dụ, hãy xem xét đoạn mã sau:
import threading
import logging
import time
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
def app_monitor():
while True:
logging.debug('Application is running smoothly.')
time.sleep(1)
monitor_thread = threading.Thread(target=app_monitor)
monitor_thread.daemon = True
monitor_thread.start()
logging.debug('Starting the application...')
time.sleep(5)
logging.debug('Application has finished.')
Trong đoạn mã này, chúng ta tạo một daemon thread (monitor_thread
) để ghi lại thông tin về tình trạng của ứng dụng mỗi giây một lần. Sau đó, chúng ta khởi động ứng dụng, đợi 5 giây, sau đó đánh dấu rằng ứng dụng đã kết thúc. Khi ứng dụng kết thúc, daemon thread cũng sẽ dừng lại.
Lưu ý rằng khi sử dụng daemon thread, chúng ta cần đảm bảo rằng các tài nguyên (ví dụ: file, socket, …) được giải phóng đúng cách trước khi daemon thread dừng lại, bởi vì khi daemon thread dừng lại, các tài nguyên này sẽ không được giải phóng một cách đúng đắn.