zoukankan      html  css  js  c++  java
  • 手写简单的线程池

    关于线程池的详细分析,具体请看这篇帖子:https://www.cnblogs.com/reecelin/p/12334107.html

    在开始之前,我们还是再来复习一下线程池的工作流程吧,如下所示:

    img

    现在,我们可以根据上面的流程简单写个线程池,如下:

    public interface ThreadPool {
    
    
        /**
         *  添加任务
         * @param command
         * @return
         */
        boolean submit(Runnable command);
    
    
        /**
         * 关闭线程池,若有任务,则等待 任务执行完毕
         */
        void shutDown();
    
        /**
         * 立即关闭线程池
         */
        void shutDownNow();
    }
    public class MyThreadPool implements ThreadPool {
    
    
        //当前正在工作的线程数
        private int currentNum;
    
        //核心线程数
        private int corePoolSize;
        //最大核心线程数
        private static final int MAX_CORE_POOL_SIZE = 3;
    
        //线程池能容纳的最大线程数
        private int maxPoolSize;
    
        //最大线程数
        private static final int MAX_POOL_SIZE = 6;
    
        //线程池是否启动
        private volatile boolean isRunning = true;
    
        //存放添加进线程池的任务队列
        private BlockingQueue<Runnable> queue;
    
        private int queueSize;
    
        //任务队列最大长度  这里设置的比较小是为了后面可以使用拒绝策略
        private static final int MAX_QUEUE_SIZE = 20;
    
        //存储用于执行添加进线程池中任务的工作线程队列
        private List<Worker> workers;
    
        private ReentrantLock lock=new ReentrantLock();
    
        public MyThreadPool() {
            this(MAX_CORE_POOL_SIZE, MAX_POOL_SIZE, MAX_QUEUE_SIZE);
        }
    
        public MyThreadPool(int corePoolSize, int maxPoolSize, int queueSize) {
            this.corePoolSize = corePoolSize > MAX_CORE_POOL_SIZE ? MAX_CORE_POOL_SIZE : corePoolSize;
            this.maxPoolSize = maxPoolSize > MAX_POOL_SIZE ? MAX_POOL_SIZE : maxPoolSize;
            this.queueSize = queueSize > MAX_QUEUE_SIZE ? MAX_QUEUE_SIZE : queueSize;
            queue = new LinkedBlockingQueue<>(this.queueSize);
            workers = Collections.synchronizedList(new ArrayList<>(this.maxPoolSize));
            intialThreadPool();
        }
    
        private void intialThreadPool() {
            for (int i = 1; i <= this.corePoolSize; i++) {
                Worker worker = new Worker("核心线程-" + i);
                workers.add(worker);
                worker.start();
                currentNum++;
                System.out.println(DateUtil.getFormat().format(new Date())+" 核心线程-" + i + " 启动,等待执行任务");
            }
        }
    
    
        @Override
        public boolean submit(Runnable command) {
            if (isRunning) {
                //若是核心线程数还没达到最大,则新建核心线程执行任务
            if (currentNum < MAX_CORE_POOL_SIZE) {
                String threadName = "新建核心线程-" + ++this.corePoolSize;
                Worker worker = new Worker(threadName, command);
                workers.add(worker);
                worker.start();
                currentNum++;
                return true;
            } else if (currentNum >= MAX_CORE_POOL_SIZE && currentNum < MAX_POOL_SIZE) {
                //若是队列未满,则直接添加进队列
                if (queue.offer(command)) {
                    return true;
                    //若是队列已满,则创建非核心线程去执行任务
                } else {
                    String threadName = "非核心线程-" + (currentNum - MAX_CORE_POOL_SIZE);
                    Worker worker = new Worker(threadName, command);
                    workers.add(worker);
                    worker.start();
                    currentNum++;
                    return true;
    
                }
                //若是线程数已到最大,且队列也满了,则直接执行拒绝策略
            } else if (currentNum >= MAX_POOL_SIZE && !queue.offer(command)) {
                System.out.println(DateUtil.getFormat().format(new Date())+" 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:"+queue.size());
                return false;
            }
        }
            return false;
        }
    
    
        @Override
        public void shutDown() {
            while (!queue.isEmpty()) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            isRunning = false;
            for (Worker worker : workers) {
                worker.interrupt();
                // help gc
                worker = null;
            }
            queue.clear();
        }
    
        @Override
        public void shutDownNow() {
            isRunning = false;
            for (Worker worker : workers) {
                worker.interrupt();
                // help gc
                worker = null;
            }
            queue.clear();
        }
    
        private class Worker extends Thread {
    
    
            private Runnable command;
    
            public Worker(String name) {
                super(name);
            }
    
            public Worker(String name, Runnable command) {
                super(name);
                this.command = command;
            }
    
            @Override
            public void run() {
                while (isRunning || !queue.isEmpty()) {
                    if (command != null) {
                        command.run();
                        // help gc
                        command = null;
                    } else {
    
                        command = queue.poll();
                        if (command != null) {
                            command.run();
                            // help gc
                            command = null;
                        }
                    }
                }
            }
    
        }
    }
    public class MyTask implements Runnable {
    
        private int id;
    
        public MyTask(int id) {
            this.id = id;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"执行任务:"+id+" 完成");
        }
    }
    public class DateUtil {
    
        private static final String pattern="yyyy-MM-dd HH:mm:ss";
    
        private static volatile SimpleDateFormat format;
    
        private DateUtil(){}
    
        public static SimpleDateFormat getFormat(){
            if (format==null){
                synchronized (DateUtil.class){
                    if (format==null){
                        format= new SimpleDateFormat(pattern);
                    }
                }
            }
            return format;
        }
    }
    public class Test {
        public static void main(String[] args) {
            MyThreadPool pool=new MyThreadPool(2, 6, 20);
    
            for (int i = 1; i <=40 ; i++) {
                pool.submit(new MyTask(i));
            }
            pool.shutDown();
        }
    }
    

    运行测试类,控制台输出:

    2020-02-22 20:29:56 核心线程-1 启动,等待执行任务
    2020-02-22 20:29:56 核心线程-2 启动,等待执行任务
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 线程池已满负载运行,拒绝了该任务,当前任务队列大小为:20
    2020-02-22 20:29:56 核心线程-1执行任务:2 完成
    2020-02-22 20:29:56 核心线程-1执行任务:3 完成
    2020-02-22 20:29:56 核心线程-1执行任务:4 完成
    2020-02-22 20:29:56 核心线程-1执行任务:5 完成
    2020-02-22 20:29:56 核心线程-1执行任务:6 完成
    2020-02-22 20:29:56 核心线程-1执行任务:7 完成
    2020-02-22 20:29:56 核心线程-1执行任务:8 完成
    2020-02-22 20:29:56 核心线程-1执行任务:9 完成
    2020-02-22 20:29:56 核心线程-1执行任务:10 完成
    2020-02-22 20:29:56 核心线程-1执行任务:11 完成
    2020-02-22 20:29:56 核心线程-1执行任务:12 完成
    2020-02-22 20:29:56 核心线程-1执行任务:13 完成
    2020-02-22 20:29:56 核心线程-1执行任务:14 完成
    2020-02-22 20:29:56 核心线程-1执行任务:15 完成
    2020-02-22 20:29:56 核心线程-1执行任务:16 完成
    2020-02-22 20:29:56 核心线程-1执行任务:17 完成
    2020-02-22 20:29:56 核心线程-1执行任务:18 完成
    2020-02-22 20:29:56 核心线程-1执行任务:19 完成
    2020-02-22 20:29:56 核心线程-1执行任务:20 完成
    2020-02-22 20:29:56 核心线程-1执行任务:21 完成
    2020-02-22 20:29:56 新建核心线程-3执行任务:1 完成
    2020-02-22 20:29:56 非核心线程-1执行任务:23 完成
    2020-02-22 20:29:56 非核心线程-0执行任务:22 完成
    2020-02-22 20:29:56 非核心线程-2执行任务:24 完成
    

    这个只是简单的线程池,许多功能都没有完善,但对于了解线程池的执行流程有一定帮助。后面会继续完善这个demo,使其更加完整。

  • 相关阅读:
    Android ---------- 下拉刷新,上拉加载
    Android ---------- 富文本构建
    php操作字符串(移除字符,计算字符串中字符个数,分割字符串,字符串序列化
    Android ---------- 弹出层自定义布局 之 AlertDialog
    Android ---------- 延时操作
    Android ---------- TabLayout 实战 (二) 仿京东商品详情页
    定风波·莫听穿林打叶声
    hiveSQL执行,转化为MR过程
    who 命令显示关于当前在本地系统上的所有用户的信息
    hadoop中压缩与解压详解
  • 原文地址:https://www.cnblogs.com/reecelin/p/13601330.html
Copyright © 2011-2022 走看看