先上结论
当线程获得锁后,不论if判断还是while判断都会从wait()方法之后的代码开始执行。
然后重点来了!!!
当if/while判断语句块中wait()方法之后的代码执行完后,使用if判断时,接下来会直接执行if判断语句块后的代码;而使用while判断时,会再一次从while判断开始执行。也就是说,使用if判断线程被唤醒后,不管条件是否符合都会执行if判断语句块后的代码;而使用while判断线程被唤醒后,会再一次判断是否满足进入while代码块的条件。使用if判断可能会出现条件之外的结果,使用while判断则不会出现条件之外的结果。
代码解析
上代码
package Factory;
//工厂类
public class FactoryDemo {
//产品类
static class Product{
//产品数量
int num=0;
//生产产品的方法
public synchronized void add(){
//判断产品数量是否满足等待条件(分别使用if和while运行后对比结果)
if(judgeNum(num,true)){
try {
//获取线程名并在wait方法前、后,以及判断代码块之后分别作一次输出
System.out.println(Thread.currentThread().getName()+"wait");
this.wait();
System.out.println(Thread.currentThread().getName()+"结束wait");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
num++;
System.out.println(Thread.currentThread().getName()+"增加了一件货物,剩余:"+num);
//唤醒等待中的线程
this.notifyAll();
}
//消耗产品的方法
public synchronized void del(){
//判断产品数量是否满足等待条件(分别使用if和while运行后对比结果)
if(judgeNum(num,false)){
try {
//获取线程名并在wait方法前、后,以及判断代码块之后分别作一次输出
System.out.println(Thread.currentThread().getName()+"wait");
this.wait();
System.out.println(Thread.currentThread().getName()+"结束wait");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
num--;
System.out.println(Thread.currentThread().getName()+"减少了一件货物,剩余:"+num);
//唤醒等待中的线程
this.notifyAll();
}
private boolean judgeNum(int number,boolean add_del){
//add_del如果为true,表示进入是否满足add方法的判断;如果为false,表示进入是否满足del方法的判断
//当产品数量大于等于10时返回true,线程进入判断代码块中并调用wait方法
if(number>=10&&add_del){
System.out.println(Thread.currentThread().getName()+"进入判断--返回true,传入的是"+number);
return true;
}
//当产品数量小于等于0时返回true,线程进入判断代码块中并调用wait方法
if(num<=0&&!add_del){
System.out.println(Thread.currentThread().getName()+"进入判断--返回true,传入的是"+number);
return true;
}
//不满足条件则返回false
return false;
}
}
public static void main(String[] args) {
//创建产品对象
Product pd=new Product();
//创建两个生产者线程A,B以及两个消费者线程C,D,分别执行20次增加/减少操作
new Thread(()->{
for(int i=0;i<20;i++)
pd.add();
},"A").start();
new Thread(()->{
for(int i=0;i<20;i++)
pd.add();
},"B").start();
new Thread(()->{
for(int i=0;i<20;i++)
pd.del();
},"C").start();
new Thread(()->{
for(int i=0;i<20;i++)
pd.del();
},"D").start();
}
}
运行结果对比: