python任务调度算法 python线程调度_工作线程

基本说明

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

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

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

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

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

入门级别

1. 线程的创建

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

import threading

def 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 threading

def target_function():
    try:
        # 线程要执行的代码
        pass
    except 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 = condition
        self.buffer = buffer

    def run(self):
        for i in range(20):
            self.condition.acquire()
            # 缓冲区已满,等待消费者消费
            while len(self.buffer) == BUFFER_SIZE:
                print('缓冲区已满,等待消费者消费')
                self.condition.wait()

            # 生产物品并添加到缓冲区
            item = 'item %s' % i
            self.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 = condition
        self.buffer = buffer

    def 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 = event

    def 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 对象,从而实现同步。