JUC(二) | 线程池浅谈

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

一、从新建线程池谈起

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue 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源码解读
  • 上面代码中多次谈到线程池状态及拒绝策略,下一步深入理解

三、线程池状态及转换

  • 与线程的五种状态不同,线程池的五种状态及其转换如下图所示:
JUC(二) | 线程池浅谈_第1张图片
线程池的状态.png

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

四、拒绝策略

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

  • 拒绝策略演示

你可能感兴趣的:(JUC(二) | 线程池浅谈)