• 生产者消费者模式-基于线程池


    1. 为什么使用生产者消费者模式

    (1)解耦合。消费者只关心队列里面取出来的数据,不用关心数据的来源。比如,生产者服务的域名,url这些变更。

    (2)支持异步。生产者生产出来数据,直接放入队列就好了,接着生产下一个数据,不必等待。比如厨师做菜的时候,只需要把做好的菜放到传送带就接着做下一道菜。不需要有等有顾客过来把这个菜领走在做下一道;效率更高。

    (3)流量削峰。双十一零点那一刻,qps会飙升。如果为了这一小会的时间,增加机器不划算,因为平时的时候,这些机器足够用。那我可以吧这些请求放到一个队列,服务从队列中拿出请求,运算后返回给客户端。

    2. 生产者消费者图示

    3. 代码实现

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class ProducerConsumer<E> {
        private int queueSize = 5;
        private int producerNum = 2;
        private int consumerNum = 2;
        //创建一个阻塞队列
        private LinkedBlockingQueue<E> blockingQueue = null;
        //生产者线程池
        private ExecutorService producerTheadPool = null;
        //消费者线程池
        private ExecutorService consumerTheadPool = null;
    
        public ProducerConsumer(){
            blockingQueue = new LinkedBlockingQueue<>(queueSize);
            producerTheadPool = Executors.newFixedThreadPool(producerNum);
            consumerTheadPool = Executors.newFixedThreadPool(consumerNum);
        }
    
        public ProducerConsumer(int queueSize, int producerNum, int consumerNum){
            blockingQueue = new LinkedBlockingQueue<>(queueSize);
            producerTheadPool = Executors.newFixedThreadPool(producerNum);
            consumerTheadPool = Executors.newFixedThreadPool(consumerNum);
        }
    
        public void produceEleAsync(E ele){
            if(!checkSuccess()){
                return;
            }
            Producer<E> producer = new Producer<E>(this.blockingQueue, ele);
            producerTheadPool.execute(producer);
        }
    
        //执行消费过程
        public void consumeEleAsync() {
            if(!checkSuccess()){
                return;
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try {
                            E ele = blockingQueue.take();//阻塞获取数据
                            Consumer<E> consumer = new Consumer<E>(ele);
                            consumerTheadPool.execute(consumer);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    
        //判空检查
        private boolean checkSuccess(){
            if(blockingQueue!=null
                    && producerTheadPool!=null
                    && consumerTheadPool!=null){
                return true;
            }
            return false;
        }
    
        //生产者
        private class Producer<E> implements Runnable{
            private LinkedBlockingQueue<E> blockingQueue;
            private E ele;
    
            public Producer(LinkedBlockingQueue<E> blockingQueue, E ele){
                this.blockingQueue = blockingQueue;
                this.ele = ele;
            }
    
            @Override
            public void run() {
                if(this.blockingQueue!=null && ele!=null){
                    try {
                        this.blockingQueue.put(ele);
                    } catch (InterruptedException e) {
                        e.getStackTrace();
                    }
                }
            }
        }
    
        //消费者
        private class Consumer<E> implements Runnable{
            private E ele;
    
            public Consumer(E ele){
                this.ele = ele;
            }
    
            @Override
            public void run() {
                //执行消费过程
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                if(ele!=null){
                    System.out.println("消费--->" + ele.toString());
                }
            }
        }
        
    
    }
  • 相关阅读:
    SQL Server 2008R2 附件数据库问题记录
    关于.NET C#调用Sqlite的总结二
    关于.NET C#调用Sqlite的总结一
    MS Server中varchar与nvarchar的区别
    Intellij IDEA中使用Debug调试
    使用idea关联mysql时报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon'
    学Redis这篇就够了
    java的动态代理机制详解
    mybatis-sql执行流程源码分析
    mybatis
  • 原文地址:https://www.cnblogs.com/CUI-S/p/11724521.html
Copyright © 2020-2023  润新知