Python 多线程threading与多线程中join()的用法
1. 简介
多线程是指在一个程序中同时运行多个线程,每个线程执行不同的任务。在Python中,我们可以使用threading
模块来实现多线程编程。threading
模块提供了创建和管理线程的功能,使得我们能够更好地利用多核处理器的能力,提高程序的性能。
join()
是threading.Thread
类中的一个方法,用于阻塞当前线程,并等待调用该方法的线程执行完毕后再继续执行。本文将详细讲解threading
模块的用法和join()
方法的使用。
在学习本文之前,我们需要对多线程的概念和基本用法有一定了解。
2. Python多线程编程基础
在Python中,要使用多线程,首先需要导入threading
模块。然后,我们需要创建一个Thread
类的实例,将需要执行的函数作为参数传递给Thread
类的构造方法,并调用start()
方法启动线程。
下面是一个简单的例子,演示了如何使用threading
模块创建并启动线程:
import threading
import time
# 定义一个线程要执行的函数
def thread_func():
# 线程执行的代码
for i in range(5):
print(f"Thread {threading.current_thread().name}: {i}")
time.sleep(1)
# 创建线程实例并启动线程
thread = threading.Thread(target=thread_func)
thread.start()
# 主线程执行的代码
for i in range(5):
print(f"Main Thread: {i}")
time.sleep(1)
代码运行结果:
Thread Thread-1: 0
Main Thread: 0
Main Thread: 1
Thread Thread-1: 1
Main Thread: 2
Thread Thread-1: 2
Main Thread: 3
Thread Thread-1: 3
Main Thread: 4
Thread Thread-1: 4
上述代码中,我们创建了一个名为thread
的线程实例,并指定thread_func
函数作为线程要执行的代码。然后我们调用thread.start()
方法启动线程。在主线程中,我们也有一些代码需要执行,因此主线程和子线程会同时执行。输出结果显示,主线程和子线程交替执行。
3. join()
的用法
join()
是threading.Thread
类的一个方法,用于阻塞当前线程,并等待调用该方法的线程执行完毕后再继续执行。如果调用join()
方法的线程已经结束,则join()
方法立即返回。
下面是一个示例代码,演示了join()
方法的用法:
import threading
import time
# 定义一个线程要执行的函数
def thread_func():
# 线程执行的代码
for i in range(5):
print(f"Thread {threading.current_thread().name}: {i}")
time.sleep(1)
# 创建线程实例并启动线程
thread = threading.Thread(target=thread_func)
thread.start()
# 阻塞当前线程,并等待子线程执行完毕
thread.join()
# 主线程执行的代码
for i in range(5):
print(f"Main Thread: {i}")
time.sleep(1)
代码运行结果:
Thread Thread-1: 0
Thread Thread-1: 1
Thread Thread-1: 2
Thread Thread-1: 3
Thread Thread-1: 4
Main Thread: 0
Main Thread: 1
Main Thread: 2
Main Thread: 3
Main Thread: 4
上述代码中,我们在主线程中调用了thread.join()
方法,这会阻塞主线程,并等待子线程执行完毕后再继续执行。因此,输出结果显示先打印子线程的输出,然后才打印主线程的输出。
如果我们不调用join()
方法,主线程和子线程将会并发执行。下面是一个示例代码:
import threading
import time
# 定义一个线程要执行的函数
def thread_func():
# 线程执行的代码
for i in range(5):
print(f"Thread {threading.current_thread().name}: {i}")
time.sleep(1)
# 创建线程实例并启动线程
thread = threading.Thread(target=thread_func)
thread.start()
# 主线程执行的代码
for i in range(5):
print(f"Main Thread: {i}")
time.sleep(1)
代码运行结果:
Main Thread: 0
Thread Thread-1: 0
Main Thread: 1
Main Thread: 2
Thread Thread-1: 1
Main Thread: 3
Thread Thread-1: 2
Main Thread: 4
Thread Thread-1: 3
Thread Thread-1: 4
在上述代码中,我们没有调用join()
方法,因此主线程和子线程交替执行,输出结果显示先打印主线程的输出,然后才打印子线程的输出。
4. join()
方法的参数
join()
方法还可以接受一个可选的超时参数。超时参数表示最长等待多少秒,如果超过这个时间线程还没有执行完毕,则会继续执行调用join()
方法的线程。
下面是一个示例代码,演示了join()
方法的超时参数的用法:
import threading
# 定义一个线程要执行的函数
def thread_func():
# 线程执行的代码
import time
for i in range(3):
print(f"Thread {threading.current_thread().name}: {i}")
time.sleep(1)
# 创建线程实例并启动线程
thread = threading.Thread(target=thread_func)
thread.start()
# 阻塞当前线程,并等待子线程执行完毕,最长只等待2秒
thread.join(2)
# 主线程执行的代码
for i in range(3):
print(f"Main Thread: {i}")
代码运行结果:
Thread Thread-1: 0
Thread Thread-1: 1
Main Thread: 0
Thread Thread-1: 2
Main Thread: 1
Main Thread: 2
在上述代码中,我们在join()
方法中传入了2作为超时参数,即最长等待2秒。子线程需要执行3次循环,每次循环等待1秒,因此子线程总共需要执行3秒。而主线程只会执行3次循环,每次循环等待不到1秒,因此不会被子线程的join()
方法阻塞。所以,输出结果只有子线程的前两次循环和主线程的输出。
5. join()
方法的应用场景
join()
方法通常用于在主线程中等待子线程完成某个任务后再继续执行,或者在一个线程中等待其他线程的结果才能继续执行。下面是一些常见的应用场景:
等待子线程完成任务
当主线程需要等待所有子线程完成某个任务后再继续执行时,可以使用join()
方法。
import threading
# 定义一个线程要执行的函数
def thread_func():
# 线程执行的代码
import time
for i in range(3):
print(f"Thread {threading.current_thread().name}: {i}")
time.sleep(1)
# 创建线程实例并启动线程
threads = []
for i in range(3):
thread = threading.Thread(target=thread_func)
threads.append(thread)
thread.start()
# 阻塞主线程,等待所有子线程执行完毕
for thread in threads:
thread.join()
# 主线程执行的代码
print("All threads have finished.")
在上述代码中,我们创建了三个子线程并启动它们。然后,在主线程中遍历子线程列表,并调用每个子线程的join()
方法,以阻塞主线程并等待子线程执行完毕。最后,主线程打印一条消息说明所有子线程已经完成。
依次执行线程
有时,我们需要在一个线程结束后再启动下一个线程。可以使用join()
方法来实现线程的按顺序执行。
import threading
# 定义一个线程要执行的函数
def thread_func(name):
# 线程执行的代码
import time
for i in range(3):
print(f"Thread {name}: {i}")
time.sleep(1)
# 创建线程实例并启动线程
thread1 = threading.Thread(target=thread_func, args=("A",))
thread2 = threading.Thread(target=thread_func, args=("B",))
thread3 = threading.Thread(target=thread_func, args=("C",))
# 启动线程1
thread1.start()
thread1.join()
# 启动线程2
thread2.start()
thread2.join()
# 启动线程3
thread3.start()
thread3.join()
# 主线程执行的代码
print("All threads have finished.")
在上述代码中,我们依次启动线程1、线程2和线程3,并分别调用join()
方法来保证线程按照顺序执行。主线程在所有子线程执行完毕后打印一条消息。
等待其他线程结果
有时候,一个线程需要等待其他几个线程的结果才能继续执行。可以使用join()
方法来实现线程间的协作。
import threading
results = []
def worker1():
import time
result = "Worker 1 result"
time.sleep(3)
results.append(result)
def worker2():
import time
result = "Worker 2 result"
time.sleep(5)
results.append(result)
# 创建线程实例并启动线程
thread1 = threading.Thread(target=worker1)
thread2 = threading.Thread(target=worker2)
# 启动线程1
thread1.start()
# 启动线程2
thread2.start()
# 等待线程1和线程2执行完毕
thread1.join()
thread2.join()
# 主线程获取线程1和线程2的结果
print(f"Worker 1 result: {results[0]}")
print(f"Worker 2 result: {results[1]}")
在上述代码中,worker1()
和worker2()
函数代表两个工作线程,它们分别模拟了需要一定时间才能完成的耗时任务。主线程需要等待线程1和线程2执行完毕后才能获取它们的结果。通过调用join()
方法,主线程被阻塞直到线程1和线程2结束。然后,主线程获取工作线程的结果并打印输出。
总结
本文详细介绍了Python threading
模块的用法和join()
方法的使用。我们学习了如何通过threading.Thread
类来创建和启动线程,以及使用join()
方法来阻塞当前线程并等待其他线程执行完毕后再继续执行。join()
方法的超时参数可以设置等待的最长时间。通过合理使用多线程和join()
方法,我们可以实现并发执行任务、按顺序执行线程和线程间的协作。