wait和join的区别
wait和join在使用上都是等待。
但是join是等待其他线程结束,而wait是等待其他线程的notify通知再运行。
当拿到锁的线程,发现要执行的任务时机不成熟的时候,使用wait进行阻塞等待,然后等时机成熟了再notify通知他可以接着走了。
这样的使用可以大大约束线程的运行顺序,此外他还有以下优点:
优势 | 说明 |
---|---|
节省 CPU | 替代忙等待,线程挂起时不消耗资源。 |
精准唤醒 | 通过 notify 按条件触发,避免无效轮询。 |
线程安全 | 自动释放/重新获取锁,避免死锁和竞态条件。 |
轻量级 | 无需额外库,内置 synchronized 即可实现。 |
使用方法与注意事项
wait和notify是Object的方法,任意一个类都可以使用。
java
Object.wait();
调用 wait()
前必须获得对象的监视器锁(即 synchronized
),这里需要保证对象是同一个。
java
synchronized(locker) {
locker.wait();
}
在执行wait操作的时候是必须要加上锁的,代码进入 wait,就会先释放锁,并且阻塞等待如果其他线程做完了必要的工作,调用 notify 唤醒这个 wait 线程wait 就会解除阻塞, 重新获取到锁. 继续执行并返回
java
synchronized(locker) {
//加锁状态
locker.wait();//临时解锁
//再加锁
}
在执行notify的时候虽然不涉及加锁操作,但是java强制要求搭配synchronized来使用
java
Thread t2 = new Thread(()->{
synchronized (locker1) {
locker1.notify();
}
});
而在执行notify的时候也要保证这两个是同一个对象,这个共同的对象就是他俩沟通的桥梁,如果是两个不同的对象,则没有任何作用。
java
Thread t1 = new Thread(()->{
synchronized (locker1) {
locker1.wait();
}
});
Thread t2 = new Thread(()->{
synchronized (locker2) {
locker2.notify();
//对于loker1的wait不会起到任何作用
}
});
如果有多个线程处于这个锁的wait等待状态,notify会随机唤醒一个线程,notify一次只会唤醒一个线程,nootifyAll方法可以唤醒所有线程。
java
Thread t1 = new Thread(()->{
synchronized (locker1) {
locker1.notifyAll();
//唤醒所有loker1的线程
}
});
wait方法不传入参数时处于"死等"模式,如果传入时间,过了这个时间就不再等待,和join方法类似。
java
Thread t1 = new Thread(()->{
synchronized (locker1) {
locker1.wait(1000);
//等待1s
}
});
务必要确保, 先 wait,后 notify,才有作用如果是先 notify, 后 wait, 此时 wait 无法被唤醒.notify 的这个线程,也没有副作用(notify 一个没有在 wait 的对象,不会报错)
小练习~
题目:使用两个线程交替打印 1~100 的数字,要求严格按顺序输出(线程A打印1,线程B打印2,线程A打印3...)。
🎯 核心要求
线程A负责打印奇数,线程B负责打印偶数。
必须使用 wait() 和 notify() 实现线程间协作,不能用 sleep() 或忙等待。
输出结果必须严格按顺序:1, 2, 3, 4,..., 100。
✅预期输出:
java
Thread-A: 1
Thread-B: 2
Thread-A: 3
Thread-B: 4
...
Thread-A: 99
Thread-B: 100
答案:
java
public class AlternatePrint {
private static final Object lock = new Object();
private static int num = 1;
private static final int MAX = 100;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock) {
while (num <= MAX) {
if (num % 2 == 1) {
System.out.println("Thread-A: " + num++);
lock.notify();
} else {
try { lock.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
while (num <= MAX) {
if (num % 2 == 0) {
System.out.println("Thread-B: " + num++);
lock.notify();
} else {
try { lock.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
});
t1.start();
t2.start();
}
}