> 文章列表 > 【python中的多线程了解一下?】

【python中的多线程了解一下?】

【python中的多线程了解一下?】

在这里插入图片描述

基本说明

线程(Thread)是操作系统进行调度的最小单位,是进程中的一个独立执行单元。线程与进程相比,具有更轻量级、更高效率、更易调度、共享资源等优点。

在传统的单核CPU中,操作系统通过时间片轮转算法将CPU的时间片分配给多个线程,实现并发执行。在多核CPU的环境下,多个线程可以同时运行,提高了程序的并发性和性能。

线程可以共享进程中的内存和资源,因此可以用来实现并发编程和异步编程,提高程序的执行效率和响应速度。

在Python中,可以使用threading模块来创建和管理线程。可以通过继承Thread类或者传递一个函数对象来创建一个新线程。线程启动后,可以通过join()方法等待线程执行完成。可以使用锁、条件变量、信号量等同步机制来保证线程之间的同步和安全。

线程在Python中广泛应用于多任务并发处理、GUI编程、Web应用等场景,具有重要的作用和价值。

入门级别

1. 线程的创建

使用threading模块中的Thread类可以创建一个新的线程。创建线程时需要指定线程的目标函数,即线程要执行的代码,以及传递给目标函数的参数。

import threadingdef target_function(arg1, arg2):# 线程要执行的代码pass# 创建线程
thread = threading.Thread(target=target_function, args=(arg1, arg2))

2. 线程的启动和执行

创建线程之后,需要调用start()方法来启动线程,并开始执行线程的目标函数。

# 启动线程
thread.start()# 等待线程执行完成
thread.join()

3. 线程的同步

线程在执行时会共享进程中的内存和资源,因此可能会出现竞争条件和并发访问问题。为了解决这些问题,Python提供了锁、条件变量、信号量等同步机制。

import threading# 创建锁对象
lock = threading.Lock()# 在代码中需要同步的位置使用锁来保证线程安全
with lock:# 临界区代码pass

中级级别

1. 线程池

线程池可以在程序启动时预先创建多个线程,然后将任务提交到线程池中执行。这样可以避免频繁创建和销毁线程,提高程序的性能。

import concurrent.futures# 创建线程池
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:# 提交任务到线程池中执行future = executor.submit(target_function, arg1, arg2)# 获取任务的执行结果result = future.result()

2. 线程间通信

线程之间需要进行通信时,可以使用共享内存、队列等方式进行数据传递。

import queue
import threading
import time# 创建队列对象
q = queue.Queue()# 定义生产者线程函数
def producer():# 生产者线程往队列中放入数据for i in range(10):data = f"生产者生产的数据:{i}"q.put(data)time.sleep(1)# 定义消费者线程函数
def consumer():# 消费者线程从队列中取出数据while True:if q.qsize() > 0:data = q.get()print(f"消费者消费了数据:{data}")time.sleep(1)else:time.sleep(1)# 创建生产者线程并启动
producer_thread = threading.Thread(target=producer)
producer_thread.start()# 创建消费者线程并启动
consumer_thread = threading.Thread(target=consumer)
consumer_thread.start()

3. 线程的异常处理

线程在执行过程中可能会发生异常,需要对异常进行捕获和处理,避免程序崩溃。

import threadingdef target_function():try:# 线程要执行的代码passexcept Exception as e:# 捕获异常并进行处理print(f"线程执行发生异常:{e}")# 创建线程并启动
thread = threading.Thread(target=target_function)
thread.start()

高级级别

通过condition实现生产者消费者

import threading
import time# 缓冲区大小
BUFFER_SIZE = 10# 生产者类
class Producer(threading.Thread):def __init__(self, condition, buffer):threading.Thread.__init__(self)self.condition = conditionself.buffer = bufferdef run(self):for i in range(20):self.condition.acquire()# 缓冲区已满,等待消费者消费while len(self.buffer) == BUFFER_SIZE:print('缓冲区已满,等待消费者消费')self.condition.wait()# 生产物品并添加到缓冲区item = 'item %s' % iself.buffer.append(item)print('生产者生产 %s' % item)# 通知消费者可以消费了self.condition.notify()self.condition.release()time.sleep(1)# 消费者类
class Consumer(threading.Thread):def __init__(self, condition, buffer):threading.Thread.__init__(self)self.condition = conditionself.buffer = bufferdef run(self):for i in range(20):self.condition.acquire()# 缓冲区为空,等待生产者生产while len(self.buffer) == 0:print('缓冲区为空,等待生产者生产')self.condition.wait()# 从缓冲区取出物品并消费item = self.buffer.pop(0)print('消费者消费 %s' % item)# 通知生产者可以生产了self.condition.notify()self.condition.release()time.sleep(1)if __name__ == '__main__':buffer = []condition = threading.Condition()producer = Producer(condition, buffer)consumer = Consumer(condition, buffer)producer.start()consumer.start()producer.join()consumer.join()

上面的代码实现了一个生产者-消费者模型,其中生产者和消费者通过共享缓冲区进行通信。代码中使用了 Python 的 threading 模块中的 Condition 对象来同步生产者和消费者线程。

在程序运行时,首先创建了一个空缓冲区和一个 Condition 对象。生产者和消费者线程分别传入这个 Condition 对象和共享的缓冲区进行初始化。然后启动生产者和消费者线程,开始生产和消费物品。生产者线程每隔 1 秒生产一个物品并将其添加到缓冲区,如果缓冲区已满则等待消费者线程消费。消费者线程每隔 1 秒从缓冲区中取出一个物品进行消费,如果缓冲区为空则等待生产者线程生产。

在生产者和消费者线程进行生产和消费操作时,都需要首先获取 Condition 对象的锁,然后通过 Condition 对象的 wait 方法进入等待状态,直到其他线程通知它们可以继续执行。当一个线程生产或消费完毕后,通过 Condition 对象的 notify 方法通知其他线程可以继续执行,然后释放 Condition 对象的锁,让其他线程进入执行状态。

通过 Condition 对象的 wait、notify 和 release 方法,可以实现线程间的同步,保证生产者和消费者线程在共享缓冲区的操作时不会互相干扰,从而避免了竞态条件和死锁等问题。

import threading
import time
# 工作线程类
class Worker(threading.Thread):def __init__(self, event):threading.Thread.__init__(self)self.event = eventdef run(self):print('工作线程 %s 等待事件' % self.name)self.event.wait()  # 等待事件print('工作线程 %s 收到事件,开始工作' % self.name)# 主线程
if __name__ == '__main__':event = threading.Event()threads = []# 创建 5 个工作线程for i in range(5):t = Worker(event)threads.append(t)t.start()# 主线程等待 3 秒后发送事件print('主线程等待 3 秒后发送事件')for i in range(3):print(i+1)time.sleep(1)event.set()  # 发送事件# 等待所有工作线程完成for t in threads:t.join()print('所有工作线程完成')

在上面的代码中,主线程创建了一个 Event 对象,并创建了 5 个工作线程并启动它们。工作线程通过调用 Event 对象的 wait 方法进入等待状态,等待主线程发送事件。主线程等待 3 秒后发送事件,通知工作线程可以开始工作。当一个工作线程收到事件后,通过打印一条消息表示开始工作。主线程等待所有工作线程完成后,打印一条消息表示所有工作线程都已完成。

通过 Event 对象的 wait 和 set 方法,可以实现多个线程之间的同步。wait 方法用于等待事件,如果事件未发生则一直阻塞线程,直到事件被其他线程发生为止。set 方法用于发送事件,通知其他等待线程可以继续执行。多个线程可以共享同一个 Event 对象,从而实现同步。

E客网络