生产者和消费的模式的一种实现

本文介绍了一种常用的并发编程模式——生产者消费者模式。通过使用阻塞队列作为缓冲区,可以有效平衡生产者和消费者之间的数据处理能力。文章提供了一个Java实现的例子,展示了如何利用LinkedBlockingQueue的take()和put()方法确保线程安全。
摘要由CSDN通过智能技术生成

1.概念

在并发编程中,经常会提到生产者和消费者模式这一概念,这个东西往往是用来提高并发编程的效率的。所谓生产者就是产生数据的线程,所谓消费者,就是消费数据的线程。再多线程并发编程中,很有可能出现生产者的身生产速度和消费者的消费速度不一致的时候,如果不采取一定的措施,肯定是会储出现意想不到的后果的,所以,往往会用一个阻塞队列来充当一个缓冲区的作用,生产者生产的数据全部放倒阻塞队列中,消费者校消费数据的时候也从阻塞队列中去那,这就可以平衡生产者和消费者的数据处理能力。

2.实现

解决生产者和消费者的关键在于使用一个阻塞队列充当缓冲区,而这个阻塞队列必须具备两个特点:1.在取数据的时候,如果队列为空,取数据的线程必须被阻塞,直到生产者生产的新的数据并且放入队列为止。2.在生产数据的时候,如果发现队列满了,此时生产者必须被阻塞,直到阻塞队列有了空位为止,才能继续生产。
在Java中,LinkedBlockingQueuetake()put()方法正好符合这两个条件,并且是线程安全的。
take():在队列为空的时候会阻塞,直到有队列有新的元素进来。
put(): 在队列满了的时候会阻塞,直到队列有了新的空位。

还是直接上代码吧:


public class ProducerAndConsumer {
    static BlockingQueue<Fruit> fruitsBuffer = new LinkedBlockingQueue<>();
    public static void main(String[] args) {
        Thread p1 = new Thread(new Producer(fruitsBuffer), "producer 1 ");
        Thread c1 = new Thread(new Consumer(fruitsBuffer),"consumer 1 ");
        Thread c2 = new Thread(new Consumer(fruitsBuffer),"consumer 2 ");
        Thread c3 = new Thread(new Consumer(fruitsBuffer),"consumer 3 ");
        p1.start();
        c1.start();
        c2.start();
        c3.start();
    }

    //生产者
    static class Producer implements Runnable {
        BlockingQueue<Fruit> productsBuffer;
        public Producer(BlockingQueue<Fruit> productsBuffer) {
            this.productsBuffer = productsBuffer;
        }
        @Override
        public void run() {
            try {
                for (int i = 0; i < 30; i++) {
                    System.out.println(Thread.currentThread().getName() + ":生产者开始生产商品了!");
                    productsBuffer.put(new Fruit( "水果:"+ i));
                    System.out.println(Thread.currentThread().getName() + ":这一次生产结束了");
                    Thread.sleep(2000);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class Consumer implements Runnable {
        BlockingQueue<Fruit> productsBuffer;

        public Consumer(BlockingQueue<Fruit> productsBuffer) {
            this.productsBuffer = productsBuffer;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Fruit product = productsBuffer.take();
                    System.out.println(Thread.currentThread().getName()+"本次消费的产品是:" + product);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //产品,水果
    static class Fruit {
        String name;

        public Fruit(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Fruit{" +
                    "name='" + name + '\'' +
                    '}';
        }

    }
}

可以看到,1个生产者和3个消费者共享了一个阻塞队列,无论数据发送得快,还是慢,最中都会被正确地处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值