Java生产者、消费者模型——经典的多线程例子

 

目录

一.简要介绍

1.涉及的两类线程:

2.涉及的java程序 

java中object类中的三个方法

二.少说多做,直接上代码

1.建立生产者

2.建立消费者

3.建立仓库

4.建立主程序

5.启动线程

得到如封面结果,实现存一个快递,取一个快递,对号入座。


一.简要介绍

生产者消费者模型是多线程的经典例子

1.涉及的两类线程:

  • 用生产者线程执行生产数据
  • 用消费者线程执行消费数据
  • 而两者交集的共享数据区域就像是一个仓库,仓库的容量是有限的
  • 生产者生产数据后放入仓库中,不需要care消费者有什么样的行为
  • 消费者从仓库之中拿数据,不需要care生产者有什么样的行为

生产者——仓库——消费者  ,如果不能做到时间连续,生产者不能及时生产数据,消费者不能及时取出数据,就会产生等待和唤醒问题,而Java程序正好可以用来解决这个问题。

2.涉及的java程序 

java中object类中的三个方法

  • wait()      等待功能,使当前程序等待,直到另一个线程调用这个对象的notify()和notifyAll()
  • notify()    唤醒功能,唤醒正在等待对象监视器的单个线程
  • notifyAll()     唤醒功能,唤醒正在等待对象监视器的所有线程

二.少说多做,直接上代码

需要建立四个部分,分别是生产者、消费者、仓库、主程序。

快递小哥=生产者,产品=包裹 ,仓库=快递柜

1.建立生产者

public class Producer implements Runnable {
    private  Warehouse w;
   public Producer(Warehouse w){
     this.w =w;
   }

    @Override
    public void run(){
        for(int i=1;i<=60;i++){
            w.put(i);
        }
}

}

2.建立消费者

public class Consumer implements Runnable {
      private Warehouse w;
      public Consumer(Warehouse w){
          this.w = w;
      }

    @Override
    public void run() {
    while(true){
              w.get();
          }
      }
}

3.建立仓库

public class Warehouse {
    //定义一个成员变量,表示第几个快递
    private int parcel;
    //定义一个成员变量,表示仓库的状态
    private boolean state = false;

    //提供存储快递和获取快递的操作

    //生产投递
    public synchronized void put(int parcel ) {
        //如果有包裹就等待消费
        if(state){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没有包裹,就生产投递包裹
        this.parcel = parcel;
        System.out.println("快递小哥将第"+this.parcel+"个快递包裹放入货柜");

        //投递完毕之后,修改仓库状态
        state = true;

        //唤醒其他等待的线程
        notifyAll();
    }

    //得到
    public synchronized void get(){
         //如果没有包裹,就等待生产投递
        if (!state){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果有包裹,就取出包裹
        System.out.println("消费者拿到第"+this.parcel+"个快递包裹");

        //取到包裹之后,就修改仓库状态
        state = false;

        //唤醒其他等待的线程
        notifyAll();
    }

}

4.建立主程序

public class main {
        public static void main(String[] args){
                //创建仓库对象,这是共享数据区域
                Warehouse w = new Warehouse();

                //创建生产者对象,把仓库对象作为构造方法参数传递,因为在这个类中要调用存储包裹的操作
                Producer p = new Producer(w);

                //创建消费者对象,把仓库对象作为构造方法参数传递,因为在这个类中要调用获取包裹的操作
                Consumer c = new Consumer(w);

                //创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递
                Thread t1 = new Thread(p);
                Thread t2 = new Thread(c);

                //启动线程
                t1.start();
                t2.start();
        }

}

5.启动线程

得到如封面结果,实现存一个快递,取一个快递,对号入座。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值