跳转至

Python线程

在 Python 中,线程(Thread)是执行流的最小单元,允许程序在同一进程内并发执行多个任务。Python 提供了多个模块来支持线程编程,主要包括 threadingconcurrent.futures。下面将详细介绍 Python 中线程的基本概念、创建、管理、通信以及一些常见用法。

1. 线程的基本概念

线程是操作系统调度的最小单位,与进程共享进程的资源(如内存空间),但拥有独立的执行流程。线程通常被用于处理耗时操作或需要并发执行的任务。

2. 使用 threading 模块创建和管理线程

Python 的 threading 模块提供了高级别的线程管理功能,可以轻松创建、启动和管理多个线程。

示例:使用 threading.Thread 类创建线程

import threading
import time

def worker(num):
    """线程的工作函数"""
    print(f"Worker {num} started")
    time.sleep(2)
    print(f"Worker {num} finished")

if __name__ == "__main__":
    # 创建线程对象
    thread1 = threading.Thread(target=worker, args=(1,))
    thread2 = threading.Thread(target=worker, args=(2,))

    # 启动线程
    thread1.start()
    thread2.start()

    # 等待线程结束
    thread1.join()
    thread2.join()

    print("All threads finished")

说明

  • 使用 threading.Thread 类创建线程对象,通过 target 参数指定线程执行的目标函数,通过 args 参数传递函数的参数。
  • 调用 start() 方法启动线程,调用 join() 方法等待线程结束。

运行结果

Worker 1 started
Worker 2 started
Worker 1 finished
Worker 2 finished
All threads finished
示例:继承 threading.Thread 类

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, num):
        super().__init__()
        self.num = num

    def run(self):
        """重写 run 方法,在线程启动时执行"""
        print(f"Thread {self.num} started")
        time.sleep(2)
        print(f"Thread {self.num} finished")

if __name__ == "__main__":
    # 创建线程实例并启动
    thread1 = MyThread(1)
    thread2 = MyThread(2)

    thread1.start()
    thread2.start()

    # 等待线程结束
    thread1.join()
    thread2.join()

    print("All threads finished")

说明

  • MyThread 类继承了 threading.Thread,重写了 run() 方法来定义线程的执行逻辑。
  • 创建 MyThread 实例并调用 start() 方法启动线程,调用 join() 方法等待线程结束。
  • 这种方式更加符合面向对象的设计思想,能够更好地组织和封装线程的功能。

运行结果

Thread 1 started
Thread 2 started
Thread 1 finished
Thread 2 finished
All threads finished

3. 线程间通信

线程间通信是多线程编程中重要的一部分,Python 提供了多种方式来实现线程间的数据交换,如使用 queue.Queue

示例:使用 queue.Queue 实现线程间通信

import threading
import queue
import time

def producer(queue):
    """生产者线程"""
    for i in range(5):
        queue.put(i)
        print(f"Produced: {i}")
        time.sleep(1)

def consumer(queue):
    """消费者线程"""
    while True:
        item = queue.get()
        if item is None:
            break
        print(f"Consumed: {item}")
        time.sleep(2)

if __name__ == "__main__":
    # 创建线程间通信的队列
    queue = queue.Queue()

    # 创建生产者和消费者线程
    producer_thread = threading.Thread(target=producer, args=(queue,))
    consumer_thread = threading.Thread(target=consumer, args=(queue,))

    # 启动线程
    producer_thread.start()
    consumer_thread.start()

    # 等待生产者线程结束
    producer_thread.join()

    # 停止消费者线程(放入结束标记)
    queue.put(None)
    consumer_thread.join()

    print("All threads finished")

说明

  • 使用 queue.Queue 创建线程间通信的队列,生产者线程通过 queue.put() 放入数据,消费者线程通过 queue.get() 获取数据。
  • 生产者线程在队列中放入数据后,消费者线程即可从队列中获取并处理数据。
  • 在示例中,生产者线程每隔 1 秒生产一个数据,消费者线程每隔 2 秒消费一个数据。

运行结果

Produced: 0
Consumed: 0
Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
Produced: 3
Consumed: 3
Produced: 4
Consumed: 4
All threads finished

4. 线程池的使用

线程池是管理多个线程的一种方式,可以避免频繁创建和销毁线程,提高效率。

示例:使用 concurrent.futures.ThreadPoolExecutor 实现线程池

import concurrent.futures
import time

def worker(num):
    """线程的工作函数"""
    print(f"Worker {num} started")
    time.sleep(2)
    print(f"Worker {num} finished")

if __name__ == "__main__":
    # 创建线程池,指定线程数量为2
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
        # 提交任务给线程池执行
        future1 = executor.submit(worker, 1)
        future2 = executor.submit(worker, 2)

        # 获取任务结果(阻塞方式)
        print(future1.result())
        print(future2.result())

    print("All threads finished")

说明

  • 使用 concurrent.futures.ThreadPoolExecutor 创建线程池,通过 max_workers 参数指定线程数量。
  • 使用 executor.submit() 方法提交任务给线程池执行,并返回 concurrent.futures.Future 对象。
  • 可以通过 future.result() 获取任务的返回结果(阻塞方式),也可以通过回调函数获取任务执行完成后的处理结果。

运行结果

Worker 1 started
Worker 2 started
Worker 1 finished
Worker 2 finished
All threads finished

5. 总结

Python 提供了多种方式来创建和管理线程,开发者可以根据具体的需求选择合适的方式。使用 threading 模块可以轻松创建和管理线程,实现简单的多线程编程。而使用 concurrent.futures 模块可以更加方便地实现线程池和异步执行任务。线程间通信是多线程编程的重要组成部分,通过合适的线程同步和通信机制可以避免竞态条件和数据不一致的问题。

评论