假设一个生产者生产一个产品,两个消费者A,B去取这个商品。
使用if:
A去取商品,发现空,于是等待...
B去取商品,发现空,于是等待...
生产者生产商品,唤醒他们
B先争到锁,从wait()后执行代码,跳出if,取走商品。
A后争到锁,从wait()处出发,跳出if,发现竟然没东西,取东西失败,越界。
结果
改用while
A去取商品,发现空,于是等待...
B去取商品,发现空,于是等待...
生产者生产商品,唤醒他们
B先争到锁,从wait()后执行代码,再次执行while,发现不必进入while,于是取走商品。
A后争到锁,从wait()处出发,再次执行while,符合循环条件,等待。
结果
代码生产者
1 package whileinsyn; 2 3 import java.util.List; 4 5 public class addsir implements Runnable{ 6 private List<String> list; 7 public addsir(List<String> list) { 8 this.list=list; 9 } 10 11 @Override 12 public void run() { 13 // TODO Auto-generated method stub 14 synchronized(list) { 15 System.out.println("生产者生产食品中..."); 16 try { 17 Thread.sleep(1000); 18 } catch (InterruptedException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 list.add("食品哈哈哈"); 23 System.out.println("已生产完毕食品哈哈哈.*&*."); 24 list.notifyAll(); 25 } 26 27 System.out.println("生产者今日生产量已完成..."); 28 } 29 30 }
代码消费者
1 package whileinsyn; 2 3 import java.util.List; 4 5 public class deletesir implements Runnable{ 6 private List<String> list; 7 public deletesir(List<String> list) { 8 this.list=list; 9 } 10 @Override 11 public void run() { 12 // TODO Auto-generated method stub 13 synchronized(list) { 14 while(list.size()==0) { 15 System.out.println("仓库无货,请消费者"+Thread.currentThread().getName()+"稍后再来..."); 16 try { 17 list.wait(); 18 } catch (InterruptedException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 } 23 System.out.println("消费者"+Thread.currentThread().getName()+"正在取走货物..."); 24 try { 25 Thread.sleep(1000); 26 } catch (InterruptedException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 System.out.println("消费者"+Thread.currentThread().getName()+"已取走"+list.remove(0)); 31 //list.notifyAll(); 32 } 33 } 34 35 }
主类
1 package whileinsyn; 2 3 import java.util.*; 4 5 public class Main { 6 public static void main(String[] args) throws InterruptedException { 7 List<String> list=new ArrayList<>(); 8 Thread provider=new Thread(new addsir(list)); 9 Thread consumer01=new Thread(new deletesir(list),"一号"); 10 Thread consumer02=new Thread(new deletesir(list),"二号"); 11 12 13 consumer01.start(); 14 consumer02.start(); 15 Thread.sleep(3000); 16 provider.start(); 17 18 } 19 }