Java多线程wait为什么用while而不是if?
这个问题可以用生产者消费者的例子来测试。
public class Pc {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
// new Thread(()->{
// for (int i = 0; i < 10; i++) {
// try {
// data.increment();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }, "C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
class Data{
private boolean[] arr = new boolean[10];
private int number = 0;
// 生产者
public synchronized void increment() throws InterruptedException {
if (number >= arr.length) { // if改成while
// 等待
System.out.println(Thread.currentThread().getName() + "生产者即将进入休眠,总数" + number);
this.wait();
System.out.println(Thread.currentThread().getName() + "生产者被唤醒,总数" + number);
}
this.notifyAll();
System.out.print("总数" + number + " ");
arr[number] = true;
++number;
System.out.println(Thread.currentThread().getName() + "生产=>" + number + "个");
// 通知其他线程,我+1完毕了
}
// 消费者
public synchronized void decrement() throws InterruptedException {
if (number <= 0) { // if改成while
// 等待
System.out.println(Thread.currentThread().getName() + "消费者即将进入休眠,总数" + number);
this.wait();
System.out.println(Thread.currentThread().getName() + "消费者被唤醒,总数" + number);
}
this.notifyAll();
System.out.print("总数" + number + " ");
arr[number-1] = false;
--number;
System.out.println(Thread.currentThread().getName() + "剩余=>" + number + "个");
// 通知其他线程,我-1完毕了
}
}
可以看到上面的代码用if的时候,当生产者不再生产的时候,消费者却没有停下执行wait
换成while的时候则是正常的等待wait
从上面的两个结果可以看出来,if的时候,消费者被唤醒是从如下截图的地方继续执行的。
线程被唤醒时已经处在if方法体内,它不会再去执行if条件判断,所以就顺序往下执行
使用while就不会,因为当唤醒了线程以后,它依然会去执行循环条件检测。所以不可能执行下去,保证了程序的安全。