zoukankan      html  css  js  c++  java
  • 等待-唤醒模型中的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     }
    16 
    17     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                 System.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     }
    79     
    80 }

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

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

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

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

    Object 的 wait 方法

    Condition 的 await 方法

     在换成while后,一切正常。

  • 相关阅读:
    Python利用Remove.bg接口自动消除图片背景
    解决ajxa跨域问题
    CentOS7 修改静态IP
    CentOS下 安装composer 与tp5.1
    centon 安装php-fpm+Nginx
    win10 安装selenium和使用
    Scrapy 爬虫框架入门
    Python 异常处理
    selenium和phantomjs的介绍
    MongoDB入门
  • 原文地址:https://www.cnblogs.com/mengxinJ/p/13954840.html
Copyright © 2011-2022 走看看