python 多线程

python 多线程是指在同一个程序中同时运行多个线程,每个线程都可以独立执行不同的任务。python 中的多线程实现可以通过 threading 模块来实现。

1. 线程创建

一般我们有两种方法来创建线程,一种是以某个函数来作为起点,另一种是继承Thread类。

1.1. 面向过程

获取一个Thread对象,构造参数中target是起点函数,注意不要加括号。假如起点函数有参数,则可以通过 args 输入元组参数或者kwargs 输入字典参数。

#! -*-conding=: UTF-8 -*-
import time
from threading import Thread

def task():
    print("另外开始一个子线程做任务啦")
    time.sleep(1)  # 用time.sleep模拟任务耗时
    print("子线程任务结束啦")

if __name__ == '__main__':
    print("这里是主线程")
    # 创建线程对象
    t1 = Thread(target=task)
    # 如果有参数
	# t2 = threading.Thread(target=consumer_task_queue, args=(taskqueue, db, ds, tokenizer, evaltool))
	# def consumer_task_queue(taskqueue, db, ds, tokenizer, evaltool):
    # 启动
    t1.start()
    time.sleep(0.3)
    print("主线程依然可以干别的事")

输出结果为:

这里是主线程
另外开始一个子线程做任务啦
主线程依然可以干别的事
子线程任务结束啦

1.2. 面向对象

#! -*-conding=: UTF-8 -*-
import time
from threading import Thread

class NewThread(Thread):
    def __init__(self):
        Thread.__init__(self)  # 必须步骤

    def run(self):  # 入口是名字为run的方法
        print("开始新的线程做一个任务啦")
        time.sleep(1)  # 用time.sleep模拟任务耗时
        print("这个新线程中的任务结束啦")

if __name__ == '__main__':
    print("这里是主线程")
    # 创建线程对象
    t1 = NewThread()
    # 启动
    t1.start()
    time.sleep(0.3)  # 这里如果主线程结束,子线程会立刻退出,暂时先用sleep规避
    print("主线程依然可以干别的事")

输出结果为:

这里是主线程
开始新的线程做一个任务啦
主线程依然可以干别的事
这个新线程中的任务结束啦

2. 线程属性

2.1. 关于线程信息的函数

threading.active_count():返回当前存活的Thread对象数量。
threading.current_thread():返回当前线程的Thread对象。
threading.enumerate():列表形式返回所有存活的Thread对象。
threading.main_thread():返回主Thread对象。

2.2. Thread对象的方法及属性

Thread.name:线程的名字,没有语义,可以相同名称。
Thread.ident:线程标识符,非零整数。
Thread.Daemon:是否为守护线程。
Thread.is_alive():是否存活。
Thread.start():开始线程活动。若多次调用抛出RuntimeError。
Thread.run():用来重载的,
Thread.join(timeout=None):等待直到线程正常或异常结束。尚未开始抛出RuntimeError
Thread(group=None, target=None, name=None, args=(), kwargs={}, *, deamon=None):构造函数。

2.3. 守护线程 Daemon

在Python 3中,守护线程(daemon thread)是一种特殊的线程,它在程序运行时在后台运行,不会阻止程序的退出。当主线程退出时,守护线程也不会自动退出,而不需要等待它执行完毕。

2.3.1. 通过参数设置

在创建线程对象时,可以通过设置daemon属性为True来创建守护线程,例如:

import threading
import time

def worker():
    while True:
        print('Worker thread running')
        time.sleep(1)

# 创建守护线程
t = threading.Thread(target=worker, daemon=True)
# 启动线程
t.start()

# 主线程执行一些操作
print('Main thread running')
time.sleep(5)
print('Main thread finished')

运行结果:

Worker thread runningMain thread running

Worker thread running
Worker thread running
Worker thread running
Worker thread running
Main thread finished

在这个示例中,我们创建了一个守护线程worker(),并将daemon属性设置为True。在主线程中,我们执行了一些操作,并休眠5秒钟。由于守护线程的存在,即使主线程已经结束,守护线程仍会在后台运行。

2.3.2. 通过属性函数

设置守护线程用Thread.setDaemon(bool)

#! -*-conding=: UTF-8 -*-
import time
from threading import Thread

def task1():
    print("开始子线程1做任务1啦")
    time.sleep(1)  # 用time.sleep模拟任务耗时
    print("子线程1中的任务1结束啦")

def task2():
    print("开始子线程2做任务2啦")
    for i in range(5):
        print("任务2-{}".format(i))
        time.sleep(1)
    print("子线程2中的任务2结束啦")

if __name__ == '__main__':
    print("这里是主线程")
    # 创建线程对象
    t1 = Thread(target=task1)
    t2 = Thread(target=task2)
    t2.setDaemon(True)  # 设置为守护进程,必须在start之前
    # 启动
    t1.start()
    t2.start()
    time.sleep(1)
    print("主线程结束了")

输出结果为:

这里是主线程
开始子线程1做任务1啦
开始子线程2做任务2啦
任务2-0
主线程结束了
子线程1中的任务1结束啦任务2-1

守护线程的作用在于,当我们需要在程序运行时执行一些后台任务,但是不想让这些任务阻止程序的正常退出时,可以使用守护线程。
例如,在一个Web应用程序中,我们可能需要启动一个守护线程来定期清理缓存或者执行一些后台任务。
需要注意的是,守护线程无法完全控制其执行过程,因此不能用于一些必须在程序退出之前完成的任务。同时,守护线程不能访问一些主线程资源,例如共享内存或者打开的文件,因为这些资源可能会在主线程结束时被释放。

2.4. 线程阻塞 join

假如要让主线程等子线程结束,那么可以使用Thread.join()方法。
当调用线程对象的join()方法时,主线程将被阻塞,直到该线程执行完成或者超时。
以下是一个简单的示例:

import threading
import time

def worker():
    print('Worker thread started')
    time.sleep(2)
    print('Worker thread finished')

# 创建线程对象
t = threading.Thread(target=worker)
# 启动线程
t.start()

# 等待线程结束
t.join()

# 主线程继续执行
print('Main thread finished')

输出结果为:

Worker thread started
Worker thread finished
Main thread finished

在这个示例中,我们创建了一个子线程worker(),并使用start()方法启动线程。在主线程中,我们调用了线程对象的join()方法,让主线程等待子线程执行完毕。在子线程执行完毕后,主线程继续执行。
需要注意的是,join()方法还可以设置超时时间,以避免无限期等待线程的执行。例如:

import threading
import time

def worker():
    print('Worker thread started')
    time.sleep(2)
    print('Worker thread finished')

# 创建线程对象
t = threading.Thread(target=worker)
# 启动线程
t.start()

# 等待线程结束,最多等待3秒钟
t.join(3)

# 主线程继续执行
print('Main thread finished')

在这个示例中,我们设置了join()方法的超时时间为3秒钟,即使子线程没有执行完成,主线程也会在3秒钟后继续执行。

3. 多线程的锁机制

在 Python3 中,锁机制是一种线程同步机制,它用于协调多个线程的并发访问共享资源,以避免竞态条件的发生。
Python3 中的多线程锁机制主要是通过 threading 模块中的 Lock、RLock 和 Semaphore 等类来实现的。
Lock 类是最基本的锁,它提供了两个基本方法 acquire() 和 release(),用于获取锁和释放锁。当一个线程调用 acquire() 方法时,如果该锁没有被其他线程获取,则该线程获取到该锁并进入临界区,否则该线程就会被阻塞,直到该锁被其他线程释放为止。
RLock 类是可重入锁,它允许同一个线程多次获取该锁,每次获取都必须有对应的释放操作。如果一个线程已经获取到该锁,它可以再次获取该锁而不被阻塞,这就是可重入的特性。RLock 类提供了 acquire() 和 release() 方法,与 Lock 类相同。
Semaphore 类是信号量,它与锁类似,但可以允许多个线程同时访问某个资源,而不是像锁一样只允许一个线程访问。它提供了 acquire() 和release() 方法,用于获取和释放资源。

3.1. Lock 锁

下面是一个使用Lock类的示例代码:

import threading

counter = 0
lock = threading.Lock()

def increment():
    global counter
    for i in range(100000):
        lock.acquire()
        counter += 1
        lock.release()

threads = []
for i in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print(counter)

上面的代码中,我们定义了一个全局变量 counter 和一个 Lock 对象 lock。increment() 函数用于在循环中对 counter 进行100000次加1操作,而在每次加1之前,我们首先获取 lock,加1操作完成之后再释放 lock。这样保证了多个线程同时对 counter 进行操作时,不会产生竞争条件。
在使用锁机制时,需要注意以下几点:
1、锁是一种互斥机制,即同一时刻只能有一个线程持有锁,其他线程必须等待该线程释放锁后才能继续执行。
2、在访问共享资源前,线程需要先获取锁。如果锁已经被其他线程持有,则线程会被阻塞,直到其他线程释放锁。
3、在访问共享资源后,线程需要释放锁,以便其他线程可以获取锁并访问共享资源。
4、在使用锁时,需要保证所有线程都使用同一个锁对象。

3.2. RLock 类

3.3. Semaphore 类

4. 多线程的通信

4.1. 队列

在 Python 3 中,可以使用队列(Queue)实现多线程之间的通信。队列是线程安全的数据结构,可以实现线程之间的同步和协作,避免竞争条件和死锁问题。
Python 内置了 Queue 模块,提供了队列数据结构,它可以用于实现多线程之间的安全通信。可以使用队列的 put() 方法往队列中添加元素,使用 get() 方法从队列中取出元素。
Queue模块提供了以下几个类:
Queue:基本队列,实现FIFO(先进先出)的算法。
LifoQueue:与Queue类似,但是实现了LIFO(后进先出)的算法。
PriorityQueue:队列中的每个元素都有一个优先级,每次弹出优先级最高的元素。
SimpleQueue:类似于Queue,但是没有任务协作的功能,也就是说,不能在进程之间使用。
Queue类中最常用的方法包括:
put(item[, block[, timeout]]):将一个item放入队列,如果队列已满,block为True则阻塞,直到队列未满或超时;block为False时,则抛出queue.Full异常。
get([block[, timeout]]):从队列中取出并返回一个item,如果队列为空,block为True则阻塞,直到队列不为空或超时;block为False时,则抛出queue.Empty异常。
task_done():通知队列,一个先前放入队列的任务已经完成。
join():阻塞主线程,直到队列中所有的任务都被处理完。

from queue import Queue
import threading
import time
def product(q):  # 生产者
	kind = ('猪肉','白菜','豆沙')
	for i in range(3):
		print(threading.current_thread().name,"生产者开始生产包子")
	 	time.sleep(1)
      	q.put(kind[i%3])  # 放入包子
		print(threading.current_thread().name,"生产者的包子做完了")
		
def consumer(q):  # 消费者
	while True:
		print(threading.current_thread().name,"消费者准备吃包子")
        time.sleep(1)
		t=q.get()  # 拿出包子
		print("消费者吃了一个{}包子".format(t))
		
if __name__=='__main__':
	q=Queue(maxsize=1)
	# 启动两个生产者线程
	threading.Thread(target=product,args=(q, )).start()
	threading.Thread(target=product,args=(q, )).start()
	# 启动一个消费者线程
	threading.Thread(target=consumer,args=(q, )).start()

参考:
https://blog.csdn.net/weixin_45100742/article/details/132824377
实例:

import time
from threading import Thread
from queue import Queue

class ConsumerThread(Thread):
    def __init__(self, taskqueue):
        Thread.__init__(self)  # 必须步骤
        self._taskqueue = taskqueue

    def run(self):  # 入口是名字为run的方法
        print("开始新的线程做一个任务啦")
        while True:
            print(self._taskqueue.get())
            time.sleep(1)  # 用time.sleep模拟任务耗时
        print("这个新线程中的任务结束啦")

if __name__ == '__main__':
    print("这里是主线程")
    taskqueue = Queue(5)
    # 创建线程对象
    consumer = ConsumerThread(taskqueue)

    taskqueue.put("11111")
    taskqueue.put("22222")
    taskqueue.put("33333")
    taskqueue.put("44444")
    # 启动
    consumer.start()
    ## 等待线程执行完毕
    #consumer.join()
    time.sleep(0.3)  # 这里如果主线程结束,子线程会立刻退出,暂时先用sleep规避
    print("主线程依然可以干别的事")

运行结果:

这里是主线程
开始新的线程做一个任务啦
11111
主线程依然可以干别的事
22222
33333
44444

4.2. 事件(Event)

事件是一种同步对象,可以用于多线程之间的通信,常用于控制线程的执行顺序。可以使用事件的 set() 方法设置事件,使用 wait() 方法等待事件被设置,使用 clear() 方法清除事件。
以下是一个使用事件实现多线程间通信的示例代码:

import time
import threading

def worker1(event):
    print('Worker 1 is waiting...\n')
    event.wait()
    print('Worker 1 is running...\n')

def worker2(event):
    print('Worker 2 is waiting...\n')
    event.wait()
    print('Worker 2 is running...\n')

event = threading.Event()
t1 = threading.Thread(target=worker1, args=(event,))
t2 = threading.Thread(target=worker2, args=(event,))

t1.start()
t2.start()

print('Main thread is sleeping...\n')
time.sleep(3)
event.set()

t1.join()
t2.join()

运行结果

Worker 1 is waiting...
Worker 2 is waiting...
Main thread is sleeping...

Worker 1 is running...
Worker 2 is running...

该代码创建了两个线程,它们都等待事件被设置,当事件被设置后,它们才开始执行。在主线程中,先休眠了 3 秒钟,然后设置了事件,从而唤醒了两个线程。在实际应用中,事件可以用于控制线程的执行顺序,或者实现线程之间的协作。

4.3. 锁(Lock)

使用锁可以实现多线程间的通信,可以通过共享变量和锁的机制来实现线程间的同步和互斥。具体来说,一个线程需要访问共享变量时,首先需要获得锁,然后读取或修改共享变量的值,完成操作后再释放锁,以便其他线程访问共享变量。

import threading

class CounterThread(threading.Thread):
    def __init__(self, lock):
        super().__init__()
        self.lock = lock

    def run(self):
        global counter
        for i in range(100000):
            with self.lock:
                counter += 1

if __name__ == '__main__':
    lock = threading.Lock()
    counter = 0
    threads = [CounterThread(lock) for _ in range(10)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    print(f'counter = {counter}')

输出结果为:

counter = 1000000

在这个例子中,CounterThread 是一个继承自 threading.Thread 的线程类,它有一个成员变量 lock,用于控制对共享变量 counter 的访问。在 run 方法中,线程会循环执行一定次数的加操作,每次操作前会获取锁并对 counter 做加一操作,完成后再释放锁。在主线程中创建了 10 个 CounterThread 线程,并启动它们进行计数操作。在所有线程都执行完毕后,打印出 counter 的最终值。

4.4. 条件变量(Condition)

条件变量(Condition)是Python多线程编程中常用的线程间通信机制之一,它可以用于线程间的通信和同步,提供了一个线程等待另一个线程通知其发生了某个事件的方法。

import threading

class Producer(threading.Thread):
    def __init__(self, name, cond, max_count):
        super().__init__(name=name)
        self.cond = cond
        self.max_count = max_count

    def run(self):
        for i in range(self.max_count):
            with self.cond:
                print(f"{self.name} producing item {i}")
                self.cond.notify_all()  # 通知消费者线程
                if i < self.max_count - 1:
                    self.cond.wait()  # 等待消费者线程通知

class Consumer(threading.Thread):
    def __init__(self, name, cond, max_count):
        super().__init__(name=name)
        self.cond = cond
        self.max_count = max_count

    def run(self):
        for i in range(self.max_count):
            with self.cond:
                self.cond.notify_all()  # 通知生产者线程
                print(f"{self.name} consuming item {i}")
                if i < self.max_count - 1:
                    self.cond.wait()  # 等待生产者线程通知

cond = threading.Condition()
max_count = 10
producer = Producer("Producer", cond, max_count)
consumer = Consumer("Consumer", cond, max_count)
producer.start()
consumer.start()
producer.join()
consumer.join()

在这个示例代码中,生产者线程通过 cond.notify() 方法通知消费者线程,消费者线程通过cond.wait() 方法等待生产者线程的通知。条件变量 cond 用于实现线程之间的同步和通信,生产者线程和消费者线程在共享同一把锁的情况下,通过 with self.cond: 语句获取条件变量的锁并进入临界区,确保线程安全。

4.5. 信号量(Semaphore)

信号量(Semaphore)是一种用于控制并发访问共享资源的同步原语。它是一种计数器,用于控制多个线程对共享资源的访问。信号量维护一个计数器,初始值为一个非负整数,每当一个线程访问共享资源时,计数器减1;当计数器为0时,所有试图访问共享资源的线程都会被阻塞,直到某个线程释放了共享资源,此时计数器加1,被阻塞的线程才有机会继续执行。
在 Python 中,我们可以使用 threading.Semaphore 类来创建信号量对象。该类的构造函数接受一个整数作为参数,表示初始计数器的值。Semaphore 类有两个方法,acquire() 和 release(),分别用于获取和释放信号量。

import threading

class Producer(threading.Thread):
    def __init__(self, name, buf, sem):
        super().__init__(name=name)
        self.buf = buf
        self.sem = sem

    def run(self):
        for i in range(5):
            self.sem.acquire()
            self.buf.append(i)
            print(f"{self.name} produced {i}")
            self.sem.release()

class Consumer(threading.Thread):
    def __init__(self, name, buf, sem):
        super().__init__(name=name)
        self.buf = buf
        self.sem = sem

    def run(self):
        while True:
            self.sem.acquire()
            if not self.buf:
                self.sem.release()
                break
            item = self.buf.pop(0)
            print(f"{self.name} consumed {item}")
            self.sem.release()

if __name__ == '__main__':
    buf = []
    sem = threading.Semaphore(1)
    producer = Producer("Producer", buf, sem)
    consumer1 = Consumer("Consumer1", buf, sem)
    consumer2 = Consumer("Consumer2", buf, sem)
    producer.start()
    consumer1.start()
    consumer2.start()
    producer.join()
    consumer1.join()
    consumer2.join()

在这个示例代码中,有一个生产者线程和两个消费者线程。生产者线程向共享缓冲区中添加数据,而消费者线程从缓冲区中获取数据。为了避免竞争条件,我们使用了信号量。
在生产者线程中,当信号量可用时,它会获取信号量并添加数据到缓冲区中,然后释放信号量。在消费者线程中,当信号量可用时,它会获取信号量并从缓冲区中获取数据,然后释放信号量。
通过使用信号量,我们可以确保生产者和消费者线程之间的同步,从而避免了竞争条件和死锁问题。

4.6. 管道(Pipe)

在 Python3 中,可以使用 multiprocessing 模块中的 Pipe 类来实现多进程间的通信,也可以用 multiprocessing.connection 模块来创建多进程间的通信通道。下面的例子是用 Pipe 类来实现多线程间的通信:

import threading
from multiprocessing import Pipe

def producer(pipe):
    for i in range(5):
        pipe.send(i)
        print(f"{threading.current_thread().name} produced {i}")
    pipe.close()

def consumer(pipe):
    while True:
        try:
            item = pipe.recv()
            print(f"{threading.current_thread().name} consumed {item}")
        except EOFError:
            break

if __name__ == '__main__':
    producer_conn, consumer_conn = Pipe()
    producer_thread = threading.Thread(target=producer, args=(producer_conn,))
    consumer_thread = threading.Thread(target=consumer, args=(consumer_conn,))
    producer_thread.start()
    consumer_thread.start()
    producer_thread.join()
    consumer_thread.join()

在这个例子中,我们创建了两个线程,一个生产者线程和一个消费者线程。它们之间共享一个管道(Pipe),其中生产者将数据写入管道,而消费者从管道中读取数据。当生产者完成其工作后,它会关闭管道以通知消费者停止运行。
需要注意的是,在 Pipe 中,发送和接收操作是阻塞的。因此,在发送或接收数据时,如果没有可用的空间或数据,线程将被阻塞,直到有数据可用或空间可用。

4.5. 定时器Timer

定时器(Timer)是Python中的一个线程类,它可以在一定时间之后调用指定的函数或方法。Timer是继承自Thread类的,因此可以像Thread一样启动、停止和等待它。
定时器的构造函数如下:
class threading.Timer(interval, function, args=None, kwargs=None)
下面是一个使用定时器的例子:

import threading

def hello():
    print("Hello, world!")

t = threading.Timer(5.0, hello)
t.start()   # 启动定时器,等待5秒后调用hello函数

这个程序中,我们创建了一个定时器t,它会在5秒后调用hello函数,并启动定时器。程序将在启动定时器后立即继续执行,而定时器则在后台等待5秒,然后调用hello函数。
如果我们想要停止定时器,可以使用cancel()方法:
t.cancel() # 停止定时器
需要注意的是,如果定时器已经超时并且在调用函数之前被取消,那么函数将不会被调用。因此,需要在调用cancel()方法之前等待定时器超时。

5. python3线程池

5.1. concurrent.futures实现多线程

Python 3中的线程池是一种常见的多线程编程模型,可以提高多线程程序的性能和可维护性。在Python 3中,线程池可以通过标准库中的concurrent.futures模块来实现。
concurrent.futures模块定义了两个类:ThreadPoolExecutor和ProcessPoolExecutor。这两个类都实现了Python 3中的执行器(Executor)接口,提供了一种方便的方式来异步执行函数或方法,并返回其结果。
「Exectuor」 提供了如下常用方法:
submit(fn, *args, **kwargs):将 fn 函数提交给线程池。args 代表传给 fn 函数的参数,kwargs 代表以关键字参数的形式为 fn 函数传入参数。
map(func, *iterables, timeout=None, chunksize=1):该函数类似于全局函数 map(func, *iterables),只是该函数将会启动多个线程,以异步方式立即对 iterables 执行 map 处理。超时抛出TimeoutError错误。返回每个函数的结果,「注意不是返回future」。
shutdown(wait=True):关闭线程池。关闭之后线程池不再接受新任务,但会将之前提交的任务完成。
程序将task函数submit给线程池后,会返回一个Future对象,Future主要用来获取task的返回值。

「Future」 提供了如下方法:
cancel():取消该 Future 代表的线程任务。如果该任务正在执行,不可取消,则该方法返回 False;否则,程序会取消该任务,并返回 True。
cancelled():返回 Future 代表的线程任务是否被成功取消。
running():如果该 Future 代表的线程任务正在执行、不可被取消,该方法返回 True。
done():如果该 Funture 代表的线程任务被成功取消或执行完成,则该方法返回 True。
result(timeout=None):获取该 Future 代表的线程任务最后返回的结果。如果 Future 代表的线程任务还未完成,该方法将会阻塞当前线程,其中 timeout 参数指定最多阻塞多少秒。超时抛出TimeoutError,取消抛出CancelledError。
exception(timeout=None):获取该 Future 代表的线程任务所引发的异常。如果该任务成功完成,没有异常,则该方法返回 None。
add_done_callback(fn):为该 Future 代表的线程任务注册一个“回调函数”,当该任务成功完成时,程序会自动触发该 fn 函数,参数是future。
使用线程池来执行线程任务的步骤如下:
1、调用 ThreadPoolExecutor 类的构造器创建一个线程池。
2、定义一个普通函数作为线程任务。
3、调用 ThreadPoolExecutor 对象的 submit() 方法来提交线程任务。
4、当不想提交任何任务时,调用 ThreadPoolExecutor 对象的 shutdown() 方法来关闭线程池。
ThreadPoolExecutor是一个线程池执行器,可以用来执行异步任务,它管理着一个线程池,其中包含若干个线程。当一个任务被提交给执行器时,执行器会将其分配给一个线程来执行。当线程池中的所有线程都在执行任务时,新提交的任务会被放入队列中,直到有可用的线程为止。
以下是一个使用ThreadPoolExecutor的简单示例:

from concurrent.futures import ThreadPoolExecutor
import time

def worker(num):
    print(f"Worker {num} starting")
    time.sleep(1)
    print(f"Worker {num} finished")

if __name__ == '__main__':
    with ThreadPoolExecutor(max_workers=3) as executor:
        futures = [executor.submit(worker, i) for i in range(5)]
    for future in concurrent.futures.as_completed(futures):
        try:
            result = future.result()
        except Exception as e:
            print(f"Task raised an exception: {e}")
        else: 
            print(f"Task returned: {result}")

在这个例子中,我们创建了一个线程池执行器,并指定了最大线程数为3。然后我们循环提交5个任务给执行器,每个任务都是一个worker函数,并传入不同的参数。由于我们设置了最大线程数为3,所以只会有3个任务同时被执行,另外2个任务会在之后的某个时间点被执行。

执行结果会存储在Future对象中,我们可以通过as_completed()方法获取任务的执行结果。如果任务执行过程中发生了异常,result()方法会抛出相应的异常。否则,它会返回任务的执行结果。

ThreadPoolExecutor还有其他一些有用的方法,例如shutdown()方法可以等待所有已提交的任务执行完毕并关闭线程池。

总之,Python 3中的线程池提供了一种方便的方式来执行异步任务,可以大大提高多线程程序的性能和可维护性。

5.2. 使用线程池的好处和场景

使用线程池的优点是可以避免线程的频繁创建和销毁,从而提高线程的利用率,减少系统的开销。因此,当需要频繁执行短时间的任务时,可以考虑使用线程池。例如:
1、网络服务器:在服务器端接收客户端请求后,可以使用线程池来处理客户端请求,以提高服务器的并发性能。
2、图像处理:在图像处理过程中,需要频繁启动和停止线程来处理每个像素点的计算,使用线程池可以减少线程的创建和销毁,提高处理效率。
3、数据库连接池:在数据库操作中,需要频繁创建和销毁数据库连接,使用线程池可以减少这种开销,提高数据库操作的效率。
总之,当需要频繁执行短时间的任务时,可以考虑使用线程池来优化程序性能。

全文参考:
https://zhuanlan.zhihu.com/p/636771223

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值