深入线程:生产者与消费者问题

生产者与消费者问题无疑是线程间通信协作的经典案例。下面来看一看”生产者/消费者“的一个简单案例:
首先,我们定义一个缓冲区Buffer,这个缓冲区用来存取数据,但缓冲区大小为1,即每次只能存取一个数据。

public class Buffer {
    private ArrayList<Integer> list = new ArrayList<>(1);  //定义一个大小为1的数组线性表,用于存放数据

    //写入数据
    public void write(int value) {
        try {
            synchronized (this) {   //给对象加锁
                while (list.size() == 1) {
                    System.out.println("等待清空缓存...");
                    wait();        //如果缓冲区已有数据,则线程进入阻塞状态,并释放锁
                }
                list.add(value);   //添加数据
                notify();          //唤醒等待等待中的线程
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int read() {
        try {
            synchronized (this) {
                while (list.size() == 0) {   //给对象加锁
                    System.out.println("等待写入数据...");
                    wait();         //如果缓冲区没有数据,则线程进入阻塞状态,并释放锁
                }
                int value = list.get(0); //获取数据
                list.clear();           //清空缓存
                notify();               //唤醒等待等待中的线程
                return value;  
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 0;
    }
}

然后,分别设定生产者和消费者来存取数据:
1.生产者

public class Producer implements Runnable{
    private Buffer buffer;

    public Producer(Buffer buffer) {
        this.buffer = buffer;         //设定缓存区
    }

    @Override
    public void run() {
        int i = 0;
        while (true) {          //不断循环往缓冲区写入数据
            System.out.println("Producer写入" + i);
            buffer.write(i++);  //往缓存中写入数据i
            try {
                Thread.sleep((long) (Math.random() * 1000)); //每写入一个数据,休息一段时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.消费者

public class Consumer implements Runnable{
    private Buffer buffer;

    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println("Consumer读出" + buffer.read());  //不断从缓冲区读出数据
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

最后,我们写一个主类作为测试:

public class ConsumerProducer {
    private Buffer buffer = new Buffer();     //新建缓冲区
    private Producer producer;
    private Consumer consumer;
    private ExecutorService executors = Executors.newFixedThreadPool(2); //创建大小为2的线程池

    public ConsumerProducer() {
        producer = new Producer(buffer);    //新建生产者
        consumer = new Consumer(buffer);    //新建消费者
        executors.execute(producer);       //添加任务
        executors.execute(consumer);       //添加任务
        executors.shutdown();              //停止接收任务
    }

    public static void main(String[] args) {
        new ConsumerProducer();
    }
}

好的,一个生产者/消费者模型已经搭建好了!我们来看看结果吧:
这里写图片描述
结果表明,当缓存中存在数据时,消费者需要等待存入数据后才能取出;同理,缓存中没有数据时,生产者需要取出数据后才能存入。
最后,画一个图来说明一下生产者与消费者之间线程之间的关系吧!
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值