Java 线程的 await 和 wait 的实现
在 Java 中,线程的协调和通信是一个重要的主题。wait()
和 notify()
方法使得线程可以在某些情况下暂停执行,待一定条件满足后再继续执行。下面,我将一步步教你如何实现这个过程。
流程概述
在实现线程的等待与唤醒机制时,主要的流程可以概括为以下几点:
步骤 | 描述 |
---|---|
1 | 创建一个共享对象 |
2 | 创建线程并实现 run() 方法 |
3 | 在线程中调用 wait() 方法 |
4 | 调用 notify() 或 notifyAll() |
5 | 线程在适当的时候继续执行 |
每一步的实现
步骤 1:创建一个共享对象
我们首先需要一个共享对象。在这个例子中,我们会创建一个简单的类,它包含一个可以被等待的状态。
public class SharedObject {
// 当前状态
private boolean isReady = false;
// 获取状态
public synchronized boolean isReady() {
return isReady;
}
// 设置状态并通知等待的线程
public synchronized void setReady() {
isReady = true;
notify(); // 唤醒等待的线程
}
}
注释:在以上代码中,SharedObject
类包含一个布尔字段 isReady
,用于表示状态。它有两个同步的方法,一个用于获取状态,另一个用于设置并通知等待的线程。
步骤 2:创建线程并实现 run()
方法
然后,我们创建两个线程,一个用于设置状态,另一个用于等待状态改变。
public class WaitThread extends Thread {
private final SharedObject sharedObject;
public WaitThread(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
synchronized (sharedObject) {
while (!sharedObject.isReady()) {
try {
System.out.println("线程 " + Thread.currentThread().getName() + " 正在等待...");
sharedObject.wait(); // 等待状态改变
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程 " + Thread.currentThread().getName() + " 状态已改变,继续执行!");
}
}
}
注释:WaitThread
类继承自 Thread
,在其 run()
方法中,它会反复检查状态。如果状态未准备好,通过 wait()
方法等待状态改变。
步骤 3:在线程中调用 wait()
方法
上面的代码已经在 run()
方法中实现了 wait()
调用。当 wait()
被调用时,当前线程会释放锁并暂停执行,直到被其他线程唤醒。
步骤 4:调用 notify()
创建另一个线程,负责设置状态并通知等待的线程:
public class NotifyThread extends Thread {
private final SharedObject sharedObject;
public NotifyThread(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
try {
Thread.sleep(2000); // 模拟一些工作
} catch (InterruptedException e) {
e.printStackTrace();
}
sharedObject.setReady(); // 设置状态为 ready
System.out.println("线程 " + Thread.currentThread().getName() + " 设置状态为 ready!");
}
}
注释:NotifyThread
线程会在睡眠 2 秒后设置状态为 ready
,并调用 notify()
方法唤醒等待的线程。
步骤 5:线程继续执行
当状态改变时,被唤醒的线程会继续执行其后续代码。
运行示例
现在我们将所有的类结合在一个主程序中,并运行它们:
public class Main {
public static void main(String[] args) {
SharedObject sharedObject = new SharedObject();
// 创建等待线程
WaitThread waitThread = new WaitThread(sharedObject);
waitThread.start();
// 创建通知线程
NotifyThread notifyThread = new NotifyThread(sharedObject);
notifyThread.start();
}
}
注释:在 main
方法中,我们创建 SharedObject
实例,并启动等待和通知线程。
关系图
接下来我们使用 Mermaid 语法表示线程与共享对象之间的关系:
erDiagram
THREAD {
string name "线程名称"
}
SHARED_OBJECT {
boolean isReady "当前状态"
}
THREAD ||--o{ SHARED_OBJECT : waits_on
数据分布
使用 Mermaid 的饼状图表示线程状态:
pie
title 线程状态分布
"等待状态": 70
"运行状态": 30
结尾
通过上述步骤,您已经了解了如何在 Java 中使用 wait()
和 notify()
来实现线程间的等待与唤醒。请记住,wait()
必须在同步代码块中使用,否则会抛出 IllegalMonitorStateException
。使用得当,可以有效控制线程的执行顺序,同时避免死锁和资源浪费。
如果你对线程的其它特性有兴趣,不妨继续深入学习,例如使用 Semaphore
、CountDownLatch
等其他同步工具。