Java并发队列-BlockingDeque(三)

本文介绍了BlockingDeque在生产者消费者模型中的使用,特别是它如何支持快速切换数据源以提高数据处理效率。通过实例演示了如何创建和使用BlockingDeque以及两个消费者之间的数据共享机制。
摘要由CSDN通过智能技术生成

        BlockingDeque为先入先出双端队列,意思就是可以从该队列的头部和尾部同时获取数据,和上一篇的单端队列有所不同,适用场景也不同。

一、适用场景

        该队列适用于生产消费者模型,与上一篇的不同之处在于,每个消费者会有一个属于自己的产品队列,但又会将其他消费者的产品队列作为备用,以便在自己消费完自己队列里的数据之后,可以继续消费其他队列的数据。这样就起到了加快数据处理的作用。

        一般为了避免多线程的锁竞争,消费者消费自己产品队列是从头部取,消费别人的队列从尾部取。

二、demo案例

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 阻塞先入先出双端队列
 */
public class BlockingDequeDemo {


    /**
     * 消费者
     */
    static class Consumer implements Runnable{

        //当前消费者名称
        private final String name;

        //当前消费者的队列
        private final  BlockingDeque<String> deque;

        //其他消费者名称
        private final  String otherName;

        //其他消费者的队列
        private final BlockingDeque<String> otherDeque;

        //每隔interva1Ms毫秒消费一个产品
        private int interva1Ms;

        public Consumer(String name,BlockingDeque<String> deque,String otherName,BlockingDeque<String> otherDeque,int interva1Ms){
            this.name = name;
            this.interva1Ms = interva1Ms;
            this.deque = deque;
            this.otherName = otherName;
            this.otherDeque = otherDeque;
        }

        @Override
        public void run() {

            try {
                while(true){
                    //消费自己的队列
                    String product = deque.pollFirst();
                    if(product != null){
                        consume(product);
                        Thread.sleep(interva1Ms);
                        continue;
                    }
                    //消费其他队列
                    String otherProduct = otherDeque.pollLast();
                    if(otherProduct != null){
                        System.out.println(name+"从"+otherName+"窃取数据");
                        consume(otherProduct);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        /**
         * 消费行为
         * @param product 产品
         */
        private void consume(String product){
            System.out.println(name +"消费:"+product);
        }
    }

    /**
     * 生产者
     */
    static class Producer implements Runnable{

        //消费者名称
        private final String consumerName;

        //数据存储队列
        private final BlockingQueue queue;

        //产品序列号
        private final AtomicInteger productSeq;

        public Producer(String consumerName,BlockingQueue queue,AtomicInteger productSeq){
            this.consumerName = consumerName;
            this.queue = queue;
            this.productSeq = productSeq;
        }

        @Override
        public void run() {

            try {
                for(int i =0;i<20;i++){
                    queue.put(product());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        String product(){
            return "产品-"+productSeq.incrementAndGet()+" ;所属消费者应为: " + consumerName;
        }
    }


    public static void main(String[] args) {
        //消费者1,消费速度比较快的队列。
        BlockingDeque<String> deque1 = new LinkedBlockingDeque<>();
        //为消费者1生产产品,并存在队列中。
        Producer producer1 = new Producer("消费者1",deque1,new AtomicInteger(0));

        //消费者2,消费速度比较慢的队列
        BlockingDeque deque2 = new LinkedBlockingDeque();
        //为消费者2生产产品,并存在队列中
        Producer producer2 = new Producer("消费者2",deque2,new AtomicInteger(0));

        //消费者1,所属队列为deque1,若消费者1消费的快,可从deque2中窃取数据消费
        Consumer consumer1 = new Consumer("消费者1",deque1,"消费者2",deque2,2000);
        //消费者2,所属队列为deque2,若消费者2消费的快,可从deque1中窃取数据消费,因为消费间隔时间为4000毫秒,肯定是消费慢的。
        Consumer consumer2 = new Consumer("消费者2",deque2,"消费者1",deque1,4000);


        new Thread(producer1).start();
        new Thread(producer2).start();

        //等待生产者完成生产
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(consumer1).start();
        new Thread(consumer2).start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值