在编写多线程程序时,有时候需要主线程等待子线程完成后再进行下一步操作。这个功能很常见,我们可以通过各种方式来实现。下面从多个方面来讨论主线程等待子线程结束继续执行的实现方式。
一、使用join()函数等待子线程结束
join()函数是一个线程对象的方法,用于等待线程执行完成。主线程调用join()函数会被阻塞,直到子线程执行完毕才会继续执行。
import threading import time def worker(): print("子线程开始执行") time.sleep(2) print("子线程执行完毕") thread = threading.Thread(target=worker) thread.start() print("主线程开始执行") thread.join() print("主线程执行完毕")
上面的代码中,主线程调用了子线程的join()方法,主线程会被阻塞,直到子线程执行完毕才会继续执行。如果没有调用join()方法,则主线程会在子线程启动后立即执行完毕。
二、使用Semaphore等待子线程结束
Semaphore信号量是一种线程同步的原语。可以用它来实现线程之间的资源竞争和协作。Semaphore有一个计数器,当计数器大于0时,可以继续执行。当计数器为0时,需要等待其他线程释放Semaphore才能继续执行。
下面的示例使用Semaphore来实现主线程等待子线程完成的功能:
import threading import time sem = threading.Semaphore(0) def worker(): print("子线程开始执行") time.sleep(2) print("子线程执行完毕") sem.release() thread = threading.Thread(target=worker) thread.start() print("主线程开始执行") sem.acquire() print("主线程执行完毕")
在上面的代码中,Semaphore的计数器初始值为0,当子线程运行完毕后,调用Semaphore的release()方法释放资源,使得Semaphore的计数器增加1。主线程在调用acquire()方法时会被阻塞,直到子线程执行完毕后释放资源,使得Semaphore的计数器增加1,主线程才会继续执行。
三、使用Event等待子线程结束
Event是一种线程同步的原语,可以用它来实现线程之间的协作。一个线程等待另一个线程设置Event信号才能继续执行。
下面是一个使用Event等待子线程结束的示例:
import threading import time event = threading.Event() def worker(): print("子线程开始执行") time.sleep(2) print("子线程执行完毕") event.set() thread = threading.Thread(target=worker) thread.start() print("主线程开始执行") event.wait() print("主线程执行完毕")
在上面的代码中,主线程执行到event.wait()时会被阻塞,直到子线程执行完毕后设置Event信号使得event.is_set()返回True,主线程才会继续执行。
四、使用Queue等待子线程结束
Queue是一个线程安全的队列,可以用它来实现线程之间的协作和通信。主线程向队列中放置任务,子线程从队列中取出任务并执行。当队列为空时,子线程会阻塞等待。
下面是一个使用Queue等待子线程结束的示例:
import threading import time import queue q = queue.Queue() def worker(): while True: task = q.get() if task is None: break print(f"子线程开始执行任务{task}") time.sleep(2) print(f"子线程执行完毕任务{task}") print("子线程执行完毕") thread = threading.Thread(target=worker) thread.start() print("主线程开始执行") for i in range(3): q.put(i) thread.join() q.put(None) print("主线程执行完毕")
在上面的代码中,主线程向队列中放置3个任务,子线程不断从队列中取出任务并执行,直到取出任务为None时退出循环。主线程在子线程执行完毕后向队列中再放置一个空任务,使得子线程能够退出循环。