生产者和消费者

简单的生产者和消费者实现

1.main 方法

public static void main(String[] args) {
    
    // 桌子
    Desk desk = new Desk();

    // 4个消费者, 每个能同时吃10个蛋糕
    for (int i=0; i<4; i++) {
        Consumer consumer = new Consumer(desk);
        for (int j=0; j<10; j++) {
            Thread thread1 = new Thread(consumer::consume);
            thread1.start();
        }
    }

    // 4个生产者, 每个能同时做10个蛋糕
    for (int i=0; i<4; i++) {
        Producer producer = new Producer(desk);
        for (int j=0; j<10; j++) {
            Thread thread = new Thread(producer::produce);
            thread.start();
        }
    }
}

2.生产者

import java.util.Random;

public class Producer {
    // 放蛋糕的桌子
    private final Desk desk;

    public Producer(Desk desk) {
        this.desk = desk;
    }

    public void produce() {
        try {
            // 生产一个蛋糕耗时100毫秒
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Random random = new Random();
        int num = random.nextInt(1000);

        // 将蛋糕放到桌子上
        desk.add(String.valueOf(num));
    }
}

3.消费者

public class Consumer {
    // 桌子
    private final Desk desk;

    public Consumer(Desk desk) {
        this.desk = desk;
    }

    public void consume() {
        // 从桌子上拿走一个蛋糕
        String num = desk.delete();

        try {
            // 吃一个蛋糕耗时500毫秒
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

4.通道

import java.util.LinkedList;
import java.util.Queue;

public class Desk {
    // 放蛋糕的托盘
    private final Queue<String> queue;

    public Desk() {
        this.queue = new LinkedList<>();
    }

    /**
     * 将蛋糕放到托盘中
     * @param num 蛋糕编号
     */
    public synchronized void add(String num) {
        // 如果托盘中的蛋糕超过了30个, 表示放不下了, 需要等待消费
        while (queue.size() > 30) {
            try {
                this.wait(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        queue.add(num);
        System.out.println(Thread.currentThread().getName() + " 生产: " + num);
    }

    /**
     * 从托盘中取走一个蛋糕
     * @return 蛋糕编号
     */
    public synchronized String delete() {
        // 如果托盘中没有蛋糕, 需要等待生产
        while (null == queue.peek()) {
            try {
                this.wait(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        String num = queue.poll();
        System.out.println(Thread.currentThread().getName() + " 消费: " + num);
        return num;
    }
}

说明

  • 引入通道的原因是, 如果只有生产者, 那么无法保证他们生产出来的蛋糕一个不少的放进了集合里, 因为每个生产者都是一个实例对象, 而锁只能锁各自的实例对象.
  • 引入了第三者通道, 就可以把锁设置为第三者的实例对象, 这样既保证了生产数量的准确, 也简化了生产者的代码.
  • wait() 方法的执行必须先获得锁, 所以需要使用 synchronized 关键字
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值