• JAVA利用阻塞队列实现生产者消费者模式


    思路

    1. 需要一个ServiceData类代表业务数据
    2. 需要一个DataProducer类代表生产者去生产业务数据
    3. 需要一个DataConsumer类代表消费者去消费/处理业务数据
    4. 需要一个线程池去管理生产者消费者线程

    业务数据

    /**
     * 业务数据
     */
    public class ServiceData {
        // TODO: setter/getter省略 
        //业务数据属性
    }
    

    生产者代码

    import java.util.concurrent.*;
    /**
     * 生产者
     */
    public class DataProducer implements Runnable {
    
        private BlockingQueue<ServiceData> queue;
        
        public DataProducer(BlockingQueue<ServiceData> queue) {
            this.queue = queue;
        }
        
        @Override
        public void run() {
            //模拟生产十万个数据
            for (int i = 0; i < 100000; i++) {
                try {
                    ServiceData data = new ServiceData();
                    //todo 生产数据过程
                    queue.put(data);
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    消费者代码

    import java.util.concurrent.*;
    /**
     * 消费者
     */
    public class DataConsumer implements Runnable {
    
        private BlockingQueue<ServiceData> queue;
        
        public DataConsumer(BlockingQueue<ServiceData> queue) {
            this.queue = queue;
        }
    
        /**
         * 当前任务是否完成
         */
        private boolean finished;
        public boolean isFinished() {
            return finished;
        }
    
        /**
         * 判断所有消费者都完成任务
         * @param consumers
         * @return
         */
        public static boolean isAllFinished(DataConsumer... consumers) {
            for (DataConsumer consumer : consumers) {
                if (!consumer.isFinished()) {
                    return false;
                }
            }
            return true;
        }
        
        @Override
        public void run() {
            //不停消费数据,没有数据时阻塞
            while (true) {
                try {
                    ServiceData data = queue.take();
                    finished = false;
                    //todo 消费数据过程
                }catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    finished = true;
                }
            }
        }
    }
    

    线程池

    import java.util.concurrent.*;
    
    public class Test {
        public static void main(String[] args) {
            //创建一个有三个固定线程的线程池
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            //创建任务队列
            BlockingQueue<PdfUrl> queue = new LinkedBlockingQueue<>();
            //创建一个生产者
            DataProducer producer1 = new DataProducer(queue);
            //创建两个消费者
            DataConsumer consumer1 = new DataConsumer(queue);
            DataConsumer consumer2 = new DataConsumer(queue);
            //启动任务
            executorService.execute(producer1);
            executorService.execute(consumer1);
            executorService.execute(consumer2);
            //生产者生产完成后,队列空了并且消费完成,则结束
            while (true) {
                if (queue.isEmpty() && DataConsumer.isAllFinished(consumer1,consumer2)) {
                    break;
                }
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //关闭线程池,立即stop线程
            threadPool.shutdownNow();
        }
    }
    
  • 相关阅读:
    windows wmi
    python编码规范
    gogs安装
    mariadb-5.5安装
    python kafka
    delimiter关键字
    phpstorm设置背景图片
    linux 下mysql 关闭 启动
    通过下载git包来安装git
    git clone 某个链接时候报错Initialized empty Git repository in 不能克隆
  • 原文地址:https://www.cnblogs.com/xiaogblog/p/15949303.html
Copyright © 2020-2023  润新知