多线程——生产者与消费者模式

在多线程的众多应用场景中,最为经典的线程通信是生产者与消费者模式了。此模式中生产者与消费者共享同一资源,并且互相依赖,互为条件。
应用场景

  1. 假设仓库只能存放一件商品,生产者将生产出来的商品放入仓库,消费者再从仓库中取走商品去消费。
  2. 如果仓库中已经存在商品,则生产者停止生产,直到消费者消费完商品,
  3. 如果仓库中无商品,则消费者停止消费,直到生产者生产出商品。

模式分析

  1. 对于生产者,没有生产商品之前,要通知消费者等待,生产商品之后,要通知消费者消费。
  2. 对于消费者,在消费商品之后,需要通知生产者生产新的商品以供自己消费。
  3. 在生产者与消费者模式中,仅仅有synchronized是无法实现线程的通信的。

使用到的方法

方法功能
wait()表示线程等待,直到通知
wait(long timeout)指定毫秒数等待
notify()唤醒处于等待状态的线程
notifyAll()唤醒全部线程

步骤一:编写Commodity商品类

这个类在生产者与消费者模式中为主要类,此类有以下功能:

  1. 定义了boolen类型的flag来决定何时让线程等待,何时唤醒线程。
  2. 利用关键字synchronized定义了Producer的生产商品功能,与Consumer的消费商品功能。
  3. 设置了线程等待机制与唤醒机制。
class Commodity{
    private String title;//商品名称
    private String content;//商品内容
    //flag=true时,允许生产,禁止消费
    //flag=false时,允许消费,禁止生产
    private boolean flag=true;

    public synchronized void produce(String title,String content){
        if (this.flag==false){//禁止生产
            try {
                super.wait();//线程执行produce()需要等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (this.flag){//允许生产
            this.title=title;
            this.content=content;
            this.flag=!this.flag;//生产结束,将信号灯设置为false,表述允许消费
            try {
                Thread.sleep(1000);//线程休眠1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            super.notify();//唤醒线程
        }
    }

    public synchronized void consume(){
        if (this.flag){//禁止消费
            try {
                super.wait();//线程执行consume()需要等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (this.flag==false){//允许消费
            System.out.println(this.title+"---->"+this.content);
            this.flag=!this.flag;//消费结束,将信号灯设置为true,表示允许生产
            super.notify();//唤醒线程
        }
    }
}

步骤二:编写生产者与消费者

Producer与Consumer两个类都要实现Runnable接口,并且覆写其中的run()方法。

class Producer implements Runnable{
    private Commodity commodity;
    public Producer(Commodity commodity){//构造方法
        this.commodity=commodity;
    }

    @Override
    public void run() {
        for (int i = 0; i <50 ; i++) {
            if (i%2==0){//生产者生产商品
                this.commodity.produce("生产者","生产者正在生产");
            }else {
                this.commodity.produce("消费者","消费者正在消费");
            }
        }
    }
}
class Consumer implements Runnable{
    private Commodity commodity;
    public Consumer(Commodity commodity){//构造方法
        this.commodity=commodity;
    }

    @Override
    public void run() {
        for (int i = 0; i <50 ; i++) {
            this.commodity.consume();//消费者消费商品
        }
    }
}

步骤三:编写测试类

public class Producer_Consumer {
    public static void main(String[] args) {
        Commodity commodity=new Commodity();
        new Thread(new Producer(commodity)).start();//启动Producer线程
        new Thread(new Consumer(commodity)).start();//启动Consumer线程
    }
}

运行结果:
“生产者”,“生产者正在生产"与"消费者”,"消费者正在消费"交替出现,时间间隔为1s。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值