Python(threading.Thread.join())

threading.Thread.join() 是 Python threading 模块中的一个方法,用于阻塞调用它的线程,直到目标线程执行完成(即 Thread 对象的 run() 方法执行结束)。该方法通常用于确保多线程程序按照预期的顺序执行,避免主线程过早退出或与子线程出现资源竞争问题。




1. 语法

thread.join(timeout=None)
  • timeout(可选):指定最多等待目标线程终止的时间(单位:秒)。如果未提供 timeout,则主线程会无限期等待目标线程执行完成。
  • join() 不会终止线程,只是等待它结束。



2. 示例代码

2.1 基本用法:等待线程执行完成

import threading
import time

def worker():
    print("线程开始执行...")
    time.sleep(2)
    print("线程执行完毕!")

# 创建线程
t = threading.Thread(target=worker)
t.start()

print("主线程等待子线程完成...")
t.join()  # 阻塞主线程,直到 t 线程执行完毕
print("主线程继续执行!")

输出示例:

主线程等待子线程完成...
线程开始执行...
线程执行完毕!
主线程继续执行!

主线程会等待 t 线程执行完毕后,才会继续向下运行。



2.2 设置超时时间 timeout

import threading
import time

def worker():
    print("线程开始执行...")
    time.sleep(5)
    print("线程执行完毕!")

t = threading.Thread(target=worker)
t.start()

print("主线程等待 2 秒...")
t.join(timeout=2)  # 最多等待 2 秒
print("主线程继续执行!(不管子线程是否完成)")

可能的输出:

主线程等待 2 秒...
线程开始执行...
主线程继续执行!(不管子线程是否完成)
线程执行完毕!

主线程最多等待 2 秒,之后会继续执行,即使 t 线程尚未完成。



2.3 多线程并行 join()

在多个线程中使用 join() 以确保所有线程都执行完毕:

import threading
import time

def worker(n):
    print(f"线程 {n} 开始")
    time.sleep(n)
    print(f"线程 {n} 结束")

threads = []

for i in range(3):
    t = threading.Thread(target=worker, args=(i+1,))
    t.start()
    threads.append(t)

# 等待所有线程执行完成
for t in threads:
    t.join()

print("所有线程执行完毕,主线程继续!")

可能的输出:

线程 1 开始
线程 2 开始
线程 3 开始
线程 1 结束
线程 2 结束
线程 3 结束
所有线程执行完毕,主线程继续!

join() 确保所有子线程都执行完毕后,主线程才会继续执行。




3. join() 相关特性

3.1 join() 只对 start() 过的线程有效

如果 join() 在一个尚未启动的线程上调用,它不会生效:

import threading

t = threading.Thread(target=lambda: print("线程运行"))
t.join()  # 这里不会阻塞,因为线程 t 还没 start()
print("主线程继续执行")

输出:

主线程继续执行

解释: t.join() 立即返回,因为 t 线程根本没有 start() 过。



3.2 join() 不能用于主线程等待自己

如果 join() 在主线程中对自身调用,会导致死锁

import threading
import time

def worker():
    print("子线程执行中...")
    time.sleep(2)
    print("子线程执行完毕")

t = threading.Thread(target=worker)
t.start()

threading.current_thread().join()  # 试图让主线程等待自己

错误:

RuntimeError: cannot join current thread

解释: join() 会让调用它的线程阻塞等待目标线程结束,但如果主线程调用 join() 来等待自己,主线程就会永远卡住,导致死锁。



3.3 join() 不能强制结束线程

import threading
import time

def worker():
    while True:
        print("线程运行中...")
        time.sleep(1)

t = threading.Thread(target=worker)
t.start()

time.sleep(3)
t.join(timeout=1)  # 主线程等待 1 秒
print("主线程继续执行")

输出(不会停止 t 线程):

线程运行中...
线程运行中...
线程运行中...
主线程继续执行
线程运行中...
...

解释: join() 只是等待线程结束,而不是强制终止线程。要停止线程,通常需要在 worker() 里用标志位来手动退出循环。



4. join() 的实际应用场景

  1. 确保主线程等待子线程完成(避免主线程退出导致子线程被强制终止)。
  2. 控制线程执行顺序,比如一个线程的任务依赖于另一个线程的结果。
  3. 使用 timeout 限制等待时间,防止子线程运行时间过长导致主线程被无限阻塞。



5. 总结

  • join() 用于等待线程完成,阻塞主线程或调用它的线程。
  • join(timeout) 允许设定超时时间,不会强制终止线程。
  • 不能在未 start() 的线程上调用 join()
  • 不能对当前线程调用 join(),否则会死锁。
  • 不能强制终止线程,仅用于等待。

你可以在你的多线程应用中使用 join() 来保证线程按照预期的顺序执行,提高程序的稳定性和可靠性! 🚀



posted @ 2025-03-31 14:36  做梦当财神  阅读(655)  评论(0)    收藏  举报