通常建议使用具有多个线程的队列,而不是列表和.pop()。这是因为列表不是线程安全的,还是出于其他原因?
与列表相比,通常建议使用具有多个线程的队列,因为队列提供了一种线程安全的方法来处理线程间通信和数据交换。以下是在多线程环境中首选队列的主要原因:
queue.Queue
.append()
.pop()
put()``get()``task_done()``join()
threading.Lock
get()
put()
threading.Condition
下面通过一个例子来说明在多线程环境中使用队列和列表的区别:
import threading import queue import time # Create a queue q = queue.Queue() # Producer function def producer(): for i in range(10): item = f"item {i}" q.put(item) print(f"Produced {item}") time.sleep(1) # Consumer function def consumer(): while True: item = q.get() if item is None: break # Sentinel value to exit print(f"Consumed {item}") q.task_done() # Create threads producer_thread = threading.Thread(target=producer) consumer_thread = threading.Thread(target=consumer) # Start threads producer_thread.start() consumer_thread.start() # Wait for producer to finish producer_thread.join() # Signal consumer to exit q.put(None) consumer_thread.join()
import threading import time # Create a shared list and a lock shared_list = [] lock = threading.Lock() # Producer function def producer(): for i in range(10): item = f"item {i}" with lock: shared_list.append(item) print(f"Produced {item}") time.sleep(1) # Consumer function def consumer(): while True: with lock: if shared_list: item = shared_list.pop(0) print(f"Consumed {item}") else: time.sleep(0.1) # Create threads producer_thread = threading.Thread(target=producer) consumer_thread = threading.Thread(target=consumer) # Start threads producer_thread.start() consumer_thread.start() # Wait for producer to finish producer_thread.join() # Join the consumer thread (not easy to terminate cleanly) consumer_thread.join()
在基于列表的示例中,由于必须手动管理锁定,因此会产生额外的复杂性。这很容易出错,而且更难维护。另一方面,基于队列的示例利用了 的内置线程安全性和便捷方法queue.Queue,从而产生了更干净、更可靠的代码。