美文网首页
JUC(二) | 线程池浅谈

JUC(二) | 线程池浅谈

作者: 采风JS | 来源:发表于2017-07-15 19:22 被阅读0次

    前面简单学习了JUC同步辅助类,今天一起走进线程池的美妙新世界。

    一、从新建线程池谈起

        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }    
        public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue) {
            this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
                 Executors.defaultThreadFactory(), defaultHandler);
        }
    
    
    • 类的区别
      Executor是执行者接口,通过execute方法执行Runnable任务;
      ExecutorService是执行者服务接口,通过submit将任务提交给Executor执行;
      ThreadPoolExecutor是真正的实现类;
      Executors是静态工厂类,可以返回ExecutorService等;

    • 参数概念
      corePoolSize : 线程池中允许同时运行的线程数;
      maximumPoolSize : 线程池中允许创建的最大线程数;
      keepAliveTime:线程池空闲后,超过此时间的线程会被终止;
      workQueue :线程任务阻塞队列;
      defaultThreadFactory : 返回线程工厂,线程池中的线程均是由线程工厂创建;
      defaultHandler:任务添加到线程池中,线程池拒绝时采取的策略;

    二、以execute方法为重

        public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
            int c = ctl.get();
            //策略一:线程池中运行数量小于corePoolSize时,直接新建任务
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            //策略二:线程池中大于等于corePoolSize时,且线程池状态允许时,将任务添加到阻塞队列中
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                    addWorker(null, false);
            }
            //策略三:线程池中大于等于corePoolSize时,且线程池状态不允许时,直接新建任务
            else if (!addWorker(command, false))
                reject(command);
        }
    
    • addWork源码解读
    • 上面代码中多次谈到线程池状态及拒绝策略,下一步深入理解

    三、线程池状态及转换

    • 与线程的五种状态不同,线程池的五种状态及其转换如下图所示:
    线程池的状态.png

    Running:能接受新任务,且处理已添加任务;(对应于isRunning检测)
    ShutDown:不能接受新任务,可处理已添加任务;
    Stop:不能接受新任务,且会中断已处理任务;
    Tidying:所有任务已经终止;
    Terminated:Tidying状态后,执行钩子函数terminate,进入此状态;

    四、拒绝策略

    AbortPolicy:当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常;
    CallerRunsPolicy:当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务;
    DiscardOldestPolicy:当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中;
    DiscardPolicy:当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务;

    相关文章

      网友评论

          本文标题:JUC(二) | 线程池浅谈

          本文链接:https://www.haomeiwen.com/subject/cvewhxtx.html