AI智能
改变未来

等待-唤醒模型中的wait、await应使用while判断

等待-唤醒模型中,之前一直使用if进行条件判断是否达到阀值来进行阻塞,比如下面的例子

1 public class CoTest01 {2     public static void main(String[] args) {3         SynContainer container = new SynContainer();4         new Productor(container).start();5         new Consumer(container).start();6 //        new Productor(container).start();7 //        new Consumer(container).start();8     }9 }10 //生产者11 class Productor extends Thread{12     SynContainer container  ;13     public Productor(SynContainer container) {14         this.container = container;15     }1617     public void run() {18         //生产19         for(int i=0;i<100;i++) {20             container.push(new Steamedbun(i));21         }22     }23 }24 //消费者25 class Consumer extends Thread{26     SynContainer container  ;27     public Consumer(SynContainer container) {28         this.container = container;29     }30     public void run() {31         //消费32         for(int i=0;i<100;i++) {33             container.pop();34         }35     }36 }37 //缓冲区38 class SynContainer{39     List<Steamedbun> list=new ArrayList<>(); //存储容器40     //存储 生产41     public synchronized void push(Steamedbun bun) {42         //何时能生产  容器存在空间43         //不能生产 只有等待44         if(list.size() == 10) {45             try {46                 this.wait(); //线程阻塞  消费者通知生产解除47             } catch (InterruptedException e) {48                 Syst3849em.out.println(\"push 异常\");49             }50         }51         //存在空间 可以生产52         list.add(bun);53         //存在数据了,可以通知消费了54         this.notifyAll();55         System.out.println(\"生产第-->\"+list.size()+\"个馒头\");56     }57     //获取 消费58     public synchronized void pop() {59         //何时消费 容器中是否存在数据60         //没有数据 只有等待61         if(list.size() == 0) {62             try {63                 this.wait(); //线程阻塞  生产者通知消费解除64             } catch (InterruptedException e) {65             }66         }67         //存在数据可以消费68         list.remove(list.size()-1);69         this.notifyAll(); //存在空间了,可以唤醒对方生产了70         System.out.println(\"消费第\" + list.size() + \"个馒头\");71     }72 }73 //馒头74 class Steamedbun{75     int id;76     public Steamedbun(int id) {77         this.id = id;78     }7980 }

这个例子是多个线程进行生产和消费馒头,馒头的个数不能小于0,大于10。

在44和61行使用的是if判断,此时main方法里创建的是两个线程,启动后发现并不会有异常。

但是在改成四个线程后就发生异常了

根据java8 api文档可知,可能会发生虚假唤醒,所以该方法应该始终在循环中使用。

Object 的 wait 方法

Condition的 await方法

在换成while后,一切正常。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 等待-唤醒模型中的wait、await应使用while判断