• java多线程之自定义线程池


    1.背景

    线程池.....大家常用....

    自己搞一个,顺便练习一下多线程编程

    2.自定义线程代码

    2.1.拒绝策略接口

    @FunctionalInterface
    public interface MyRejectPolicy<T> {
        void reject(MyBlockingQueue<T> queue, T task);
    }

    2.2.自定义阻塞队列

    @Slf4j
    public class MyBlockingQueue<T> {
        // 1.任务队列
        private Deque<T> queue = new ArrayDeque<>();
        // 2.容量
        private int capacity;
        // 3.锁
        private ReentrantLock lock = new ReentrantLock();
        // 4.生产者条件变量
        private Condition producerCondition = lock.newCondition();
        // 5.消费者条件变量
        private Condition consumerCondition = lock.newCondition();
    
        // 构造方法
        public MyBlockingQueue(int capacity) {
            this.capacity = capacity;
        }
    
        // 阻塞获取
        public T take() {
            lock.lock();
            try {
                // 判断是否为空
                while (queue.isEmpty()) {
                    try {
                        // 无任务消费者等待
                        log.info("无任务,消费者等待....");
                        consumerCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 不为空,消费者获取一个任务
                T t = queue.removeFirst();
                log.info("消费者已获取到任务t={}", t);
                // 通知生产者放入任务
                producerCondition.signal();
                return t;
            } finally {
                lock.unlock();
            }
        }
    
        // 阻塞添加
        public void put(T t) {
            lock.lock();
            try {
                while (queue.size() >= capacity) {
                    try {
                        // 队列已满,生产者等待
                        log.info("......队列已满,生产者等待");
                        producerCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 放入队列
                queue.addLast(t);
                log.info("......生产者,以将任务放入队列");
                // 通知消费者获取任务
                consumerCondition.signal();
            } finally {
                lock.unlock();
            }
        }
    }

    2.3.自定义工作线程

    @Slf4j
    public class MyWorkerThread extends Thread {
        // 线程集合
        private HashSet<MyWorkerThread> workerThreadList = new HashSet<>();
        // 任务队列
        private MyBlockingQueue<Runnable> taskQueue;
        // 任务对象
        private Runnable task;
    
        /**
         * 构造方法
         *
         * @param task
         */
        public MyWorkerThread(HashSet<MyWorkerThread> workerThreadList, MyBlockingQueue<Runnable> taskQueue, Runnable task) {
            this.workerThreadList = workerThreadList;
            this.taskQueue = taskQueue;
            this.task = task;
        }
    
        /**
         * 执行任务
         */
        @Override
        public void run() {
            // 当【task不为空】时执行当前任务
            // 当【task为空】时,从队列中获取任务再执行
            while (task != null || ((task = taskQueue.take()) != null)) {
                try {
                    // 执行任务
                    log.info("执行当前任务:{}", task);
                    task.run();
                } finally {
                    // 将任务设置为空
                    task = null;
                }
            }
            // 无任务,释放线程
            synchronized (workerThreadList) {
                log.info("无任务,删除当前线程:{}", this);
                workerThreadList.remove(this);
            }
        }
    }

    2.4.自定义线程池

    @Slf4j
    public class MyThreadPool {
        // 核心线程数
        private int coreSize;
        // 阻塞队列
        private MyBlockingQueue<Runnable> taskQueue;
        // 线程集合
        private HashSet<MyWorkerThread> workerThreadList = new HashSet<>();
        // 拒绝策略
        private MyRejectPolicy<Runnable> rejectPolicy;
    
        /**
         * 线程池构造器
         *
         * @param coreSize
         * @param rejectPolicy
         */
        public MyThreadPool(int coreSize, MyRejectPolicy<Runnable> rejectPolicy) {
            this.coreSize = coreSize;
            this.taskQueue = new MyBlockingQueue<>(coreSize);
            this.rejectPolicy = rejectPolicy;
        }
    
        /**
         *
         */
        public void execute(Runnable task) {
            // 当任务数【没有超过】核心线程数coreSize时,直接给workerThreadList 执行
            // 当任务数【超过】核心线程数coreSize时,放入队列
            synchronized (workerThreadList) {
                int size = workerThreadList.size();
                if (size < coreSize) {
                    MyWorkerThread workerThread = new MyWorkerThread(workerThreadList, taskQueue, task);
                    workerThread.setName("工作线程-" + (size + 1));
                    log.info("创建线程对象:{},执行任务:{}", workerThread, task);
                    workerThreadList.add(workerThread);
                    workerThread.start();
                } else {
                    taskQueue.put(task);
                }
            }
        }
    }

    3.测试

    @Slf4j
    public class Test01 {
        /**
         * 测试自定义的线程池
         * @param args
         */
        public static void main(String[] args) {
            // 创建线程池
            MyThreadPool pool = new MyThreadPool(2, (queue, task) -> {
                queue.put(task);
            });
            // 执行任务
            pool.execute(()->{
                log.info("执行任务1...");
            });
            pool.execute(()->{
                log.info("执行任务2...");
            });
            pool.execute(()->{
                log.info("执行任务3...");
            });
        }
    }

    完美!

  • 相关阅读:
    Styling a Flex Button control using embedded fonts(转载)
    ArcSDE Administration Command Reference (来自ARCGIS官方)
    FlexPaper_1.2.1.swc——Flex在线显示PDF文档(使用FlexPaper)感悟
    SDE数据的备份与恢复(转载)
    C#中将dll汇入exe,并加壳(转载)
    WEB页面导出为EXCEL/WORD文档的方法 (转载)
    Property Manager Updated 1.0.0.4 小工具介绍(转载)
    Openbravo 3.0安装过程简述
    Installing "uuidossp" library in Postgres 9.1
    BindingSource的事件触发顺序
  • 原文地址:https://www.cnblogs.com/newAndHui/p/15915602.html
Copyright © 2020-2023  润新知