线程等待唤醒机制
线程等待唤醒机制是多线程编程中的重要概念,用于实现线程间的协作和同步。在 Java 里,主要通过 Object 类的 wait()、notify() 和 notifyAll() 方法,以及 Lock 接口和 Condition 接口来实现这一机制。以下为你详细介绍这两种实现方式:
使用 Object 类的 wait()、notify() 和 notifyAll() 方法
wait()、notify() 和 notifyAll() 是 Object 类的方法,任何 Java 对象都可以调用这些方法。不过,这些方法必须在 synchronized 代码块或同步方法中使用。
方法说明
wait():使当前线程进入等待状态,同时释放对象的锁,直到其他线程调用该对象的notify()或notifyAll()方法将其唤醒。notify():随机唤醒在此对象监视器上等待的一个线程。notifyAll():唤醒在此对象监视器上等待的所有线程。
示例代码
class SharedResource {
private boolean flag = false;
public synchronized void waitForSignal() throws InterruptedException {
// 当条件不满足时,线程进入等待状态
while (!flag) {
wait();
}
System.out.println(Thread.currentThread().getName() + " 被唤醒,继续执行。");
// 重置标志
flag = false;
}
public synchronized void sendSignal() {
// 设置标志
flag = true;
// 唤醒等待的线程
notify();
System.out.println(Thread.currentThread().getName() + " 发送信号,唤醒一个等待的线程。");
}
}
public class WaitNotifyExample {
public static void main(String[] args) {
SharedResource sharedResource = new SharedResource();
// 创建等待线程
Thread waitThread = new Thread(() -> {
try {
sharedResource.waitForSignal();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "WaitThread");
// 创建通知线程
Thread notifyThread = new Thread(() -> {
try {
// 模拟一些操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
sharedResource.sendSignal();
}, "NotifyThread");
waitThread.start();
notifyThread.start();
}
}
代码解释
SharedResource类包含一个flag标志,用于表示是否可以继续执行。waitForSignal()方法中,当flag为false时,线程调用wait()方法进入等待状态,直到flag变为true且被其他线程唤醒。sendSignal()方法中,将flag设置为true,并调用notify()方法唤醒一个等待的线程。
使用 Lock 接口和 Condition 接口
Lock 接口和 Condition 接口是 Java 并发包中提供的更灵活的锁和条件变量机制,与 Object 类的方法相比,Condition 可以实现更精细的线程控制。
方法说明
await():使当前线程进入等待状态,同时释放锁,直到其他线程调用该Condition对象的signal()或signalAll()方法将其唤醒。signal():随机唤醒在该Condition对象上等待的一个线程。signalAll():唤醒在该Condition对象上等待的所有线程。
示例代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SharedResourceWithLock {
private boolean flag = false;
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void waitForSignal() throws InterruptedException {
lock.lock();
try {
// 当条件不满足时,线程进入等待状态
while (!flag) {
condition.await();
}
System.out.println(Thread.currentThread().getName() + " 被唤醒,继续执行。");
// 重置标志
flag = false;
} finally {
lock.unlock();
}
}
public void sendSignal() {
lock.lock();
try {
// 设置标志
flag = true;
// 唤醒等待的线程
condition.signal();
System.out.println(Thread.currentThread().getName() + " 发送信号,唤醒一个等待的线程。");
} finally {
lock.unlock();
}
}
}
public class LockConditionExample {
public static void main(String[] args) {
SharedResourceWithLock sharedResource = new SharedResourceWithLock();
// 创建等待线程
Thread waitThread = new Thread(() -> {
try {
sharedResource.waitForSignal();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "WaitThread");
// 创建通知线程
Thread notifyThread = new Thread(() -> {
try {
// 模拟一些操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
sharedResource.sendSignal();
}, "NotifyThread");
waitThread.start();
notifyThread.start();
}
}
代码解释
SharedResourceWithLock类使用ReentrantLock作为锁,通过lock.newCondition()创建一个Condition对象。waitForSignal()方法中,当flag为false时,线程调用condition.await()方法进入等待状态,直到flag变为true且被其他线程唤醒。sendSignal()方法中,将flag设置为true,并调用condition.signal()方法唤醒一个等待的线程。
总结
Object类的方法:简单易用,适用于基本的线程等待唤醒场景,但功能相对有限。Lock接口和Condition接口:提供了更灵活的锁和条件变量机制,可以实现更精细的线程控制,适用于复杂的多线程场景。
JUC编程 文章被收录于专栏
JUC 是 Java.util.concurrent 包的简称,它是 Java 5 引入的一个用于处理并发编程的工具包,为 Java 开发者提供了一系列用于高效处理并发任务的类和接口,极大地简化了多线程编程的复杂性。

