threading
模块是 Python 中用于进行多线程编程的标准库之一。通过 threading
模块,你可以创建和管理线程,使得程序能够并发执行多个任务。以下是一些基本的 threading
模块的用法:
使用 threading.Thread
类可以创建一个新的线程。需要提供一个可调用对象(通常是一个函数),作为线程的执行体。
import threading
def my_function():
for _ in range(5):
print("Hello from thread!")
# 创建线程
my_thread = threading.Thread(target=my_function)
# 启动线程
my_thread.start()
# 主线程继续执行其他任务
for _ in range(5):
print("Hello from main thread!")
在多线程编程中,为了防止多个线程同时访问共享的资源,可以使用锁(threading.Lock
)进行线程同步。
import threading
# 共享资源
counter = 0
counter_lock = threading.Lock()
def increment_counter():
global counter
for _ in range(1000000):
with counter_lock:
counter += 1
# 创建两个线程
thread1 = threading.Thread(target=increment_counter)
thread2 = threading.Thread(target=increment_counter)
# 启动线程
thread1.start()
thread2.start()
# 等待两个线程结束
thread1.join()
thread2.join()
print("Counter:", counter)
在多线程编程中,线程之间可能需要进行通信。可以使用 threading.Event
或 queue.Queue
等机制来实现线程间的通信。
threading.Event
:import threading
def wait_for_event(event):
print("Waiting for event to be set")
event.wait()
print("Event has been set")
def set_event(event, delay):
print(f"Waiting for {delay} seconds before setting the event")
threading.Event().wait(delay)
event.set()
print("Event has been set")
# 创建事件对象
event = threading.Event()
# 创建两个线程
thread1 = threading.Thread(target=wait_for_event, args=(event,))
thread2 = threading.Thread(target=set_event, args=(event, 2))
# 启动线程
thread1.start()
thread2.start()
# 等待两个线程结束
thread1.join()
thread2.join()
使用 queue.Queue
:
import threading
import queue
def producer(queue, items):
for item in items:
queue.put(item)
def consumer(queue):
while True:
item = queue.get()
if item is None:
break
print(f"Consumed: {item}")
# 创建队列对象
my_queue = queue.Queue()
# 创建两个线程
producer_thread = threading.Thread(target=producer, args=(my_queue, range(5)))
consumer_thread = threading.Thread(target=consumer, args=(my_queue,))
# 启动线程
producer_thread.start()
consumer_thread.start()
# 等待生产者线程结束
producer_thread.join()
# 放置一个特殊值到队列中,表示消费者可以停止
my_queue.put(None)
# 等待消费者线程结束
consumer_thread.join()
虽然 threading
模块提供了简单的多线程编程接口,但在一些场景中,使用 concurrent.futures
模块中的 ThreadPoolExecutor
或 ProcessPoolExecutor
类更加方便,它们提供了高级的并发处理机制。
concurrent.futures
模块提供了更高级的并发处理机制,其中的 ThreadPoolExecutor
和 ProcessPoolExecutor
类是两个常用的工具,分别用于线程池和进程池的并发执行。这两个类都是 concurrent.futures.Executor
的子类。
ThreadPoolExecutor
提供了一个线程池,可以方便地在多个线程中执行函数。以下是一个简单的示例:
from concurrent.futures import ThreadPoolExecutor
import time
def my_function(message):
time.sleep(2)
return f"Hello, {message}!"
# 创建线程池
with ThreadPoolExecutor(max_workers=3) as executor:
# 提交任务并获取 Future 对象
future1 = executor.submit(my_function, "Alice")
future2 = executor.submit(my_function, "Bob")
# 阻塞等待任务完成并获取结果
result1 = future1.result()
result2 = future2.result()
print(result1)
print(result2)
上述代码中,ThreadPoolExecutor
创建了一个最大工作线程数为 3 的线程池,通过 submit
方法提交了两个任务,然后通过 result
方法获取任务的结果。
ProcessPoolExecutor
提供了一个进程池,可以在多个进程中执行函数。同样是一个示例:
from concurrent.futures import ProcessPoolExecutor
import time
def my_function(message):
time.sleep(2)
return f"Hello, {message}!"
# 创建进程池
with ProcessPoolExecutor(max_workers=3) as executor:
# 提交任务并获取 Future 对象
future1 = executor.submit(my_function, "Alice")
future2 = executor.submit(my_function, "Bob")
# 阻塞等待任务完成并获取结果
result1 = future1.result()
result2 = future2.result()
print(result1)
print(result2)
这段代码与上一个示例类似,不同之处在于使用了 ProcessPoolExecutor
创建了一个进程池,任务在不同的进程中执行。这使得它适用于一些 CPU 密集型的任务,可以充分利用多核处理器的性能。
简化并发编程: concurrent.futures
模块提供了更高层次的接口,简化了并发编程的复杂性。
易于管理任务: 使用 submit
方法可以方便地提交任务,并通过 Future
对象进行管理。
自动管理资源: 使用 with
语句创建 ThreadPoolExecutor
或 ProcessPoolExecutor
时,会自动管理资源的生命周期,不再需要手动管理线程或进程的启动和关闭。
可替代传统的 threading
和 multiprocessing
模块: 在某些场景下,concurrent.futures
提供了更方便的方式来进行并发编程,特别是对于一些简单的并行任务。
在实际应用中,选择使用 concurrent.futures
模块还是传统的 threading
和 multiprocessing
模块,取决于具体的需求和场景。如果你只是简单地执行一些任务,并发处理的复杂性较低,使用 concurrent.futures
可能更加方便。而对于更复杂的并发控制和线程/进程管理,传统的 threading
和 multiprocessing
模块可能更适合。