ThreadPoolExecutor

java并发编程之美 学习笔记

线程池主要解决两个问题:

  • 当大量执行异步任务时线程池能够提供较好的性能。(不使用线程池时,创建异步任务都需要new线程来执行,而线程的创建和销毁是有一定开销的)。线程池中的线程是可复用的,无需每次执行异步任务都新建和销毁。
  • 线程池提供了一种资源限制和管理的手段。如限制线程个数,动态新增线程等。

线程池也提供了许多可调参数和可扩展性接口 ,以满足不同情境的需要,程序
员可以使用更方便的 Executors的工厂方法,如newCachedThreadPool(线程自动回收),newFixedThreadPool(固定个数线程),newSingleThreadExecutor(单个线程).

ThreadPoolExecutor

ThreadPoolExecutor结构

结构1

public class ThreadPoolExecutor extends AbstractExecutorService {


	// (高3位)用来表示线程池状态,(低29位)用来表示线程个数
	//默认是RUNNING状态,线程个数为 0
 	private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));


 	//线程个数掩码位数,
 	//并不是所有平台 的工的类型都是32位的,所以准确地说, 是具体平台 下 Integer的二进制位数 - 3后的剩余位数所表示的数才是线程的个数
 	private static final int COUNT_BITS = Integer.SIZE - 3;

 	//线程最大个数 (低29位)
 	// 000000000 000000000 000000000 000000001 << 29 = 00100000 000000000 000000000 000000000
 	// 00100000 000000000 000000000 000000000 -1 = 00011111 11111111 11111111 11111111
 	private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

 	
    /**
     * java使用补码的形式表示负数:如 -1:
     * 1的原码 00000000 00000000 00000000 00000001  
     * 1的反码 1111111 11111111 11111111 11111110
     * 1的补码(反码末位加1) : 11111111 11111111 111111111 11111111
     * 
     */
    //线程池状态
 	//(高3位)  11111111 11111111 111111111 11111111 << 29 ==  11100000 000000000 000000000 000000000
    private static final int RUNNING    = -1 << COUNT_BITS;

	// (高3位) 
 	// 00000000 000000000 000000000 000000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;

    //(高3位) 00000000 00000000 00000000 00000001 << 29 = 00100000 00000000 00000000 00000000
    private static final int STOP       =  1 << COUNT_BITS;

 	// (高3位) 0000000 00000000 00000000 00000010 << 29 = 01000000 00000000 00000000 00000000 
    private static final int TIDYING    =  2 << COUNT_BITS;

 	// (高3位) 0000000 00000000 00000000 00000011 << 29 = 01100000 00000000 00000000 00000000 
    private static final int TERMINATED =  3 << COUNT_BITS;

    //获取高 3位(运行状态)
    // CAPACITY:    00011111 11111111 11111111 11111111
    // ~CAPACITY:   11100000 000000000 000000000 000000000
    private static int runStateOf(int c)     { return c & ~CAPACITY; }

    //获取低29位(线程个数)
    private static int workerCountOf(int c)  { return c & CAPACITY; }

    //计算ctl值(线程池状态 | 线程个数)
    private static int ctlOf(int rs, int wc) { return rs | wc; }

}

ctl使用

  • 高3位表示:线程池状态
  • 低29位表示:线程个数

线程池状态如下:

  • RUNNING(111 0~29): 接受新任务 && 处理阻塞队列里的任务。
  • SHUTDOWN(000 0~29): 拒绝新任务,但是处理阻塞队列里的任务。
  • STOP(001 0~29): 拒绝新任务 && 抛弃阻塞队列里任务,同时中断正在处理的任务。
  • TIDYING(010 0~29): 所有任务都执行完成(包含阻塞队列[此时为空]),线程池活动线程数为0,将要调用terminated()方法
  • TREMINATED(011 0~29): 终止状态。terminated()方法执行完后的状态。

线程池状态转换图:
在这里插入图片描述

结构2

    //用于保存待执行的任务的阻塞队列。
    private final BlockingQueue<Runnable> workQueue;

    //后续分析.....
    private final ReentrantLock mainLock = new ReentrantLock();
    private final HashSet<Worker> workers = new HashSet<Worker>();
    private final Condition termination = mainLock.newCondition();
    private int largestPoolSize;
    private long completedTaskCount;


    //创建线程的工厂 。
    private volatile ThreadFactory threadFactory;

     //饱和策略: 当队列满 && 线程个数达到maximumPoolSize后采取的策略。
    private volatile RejectedExecutionHandler handler;

    //当线程池中线程数量 > 核心线程数, 且线程池中存在idle线程; 表示这些idle线程最大存活时间。
    private volatile long keepAliveTime;

    /**
     * If false :核心线程永远存在(即便核心线程处于idle状态)
     * If true : 使用keepAliveTime来控制核心线程数
     */
    private volatile boolean allowCoreThreadTimeOut;

    // 线程池核心线程个数
    private volatile int corePoolSize;

    //线程池最大线程数量。
    private volatile int maximumPoolSize;

   
    //默认饱和策略 --- AbortPolicy -抛出异常
    private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();

ThreadPoolExecutor构造方法参数说明

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 
  • corePoolSize 保持在池中的线程数量,如果没有设置allowCoreThreadTimeout参数,即使这些线程空闲也将一直保持在池中
  • maximumPoolSize 线程池中的最大线程数量
  • keepAliveTime 当线程池中空闲线程数量超过corePoolSize时,多余的线程会超过这个保活时间会被销毁;
  • unit keepAliveTime的单位
  • workQueue :任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种;
  • threadFactory 线程工厂,用于创建线程,一般用默认即可;
  • handler 拒绝策略;当任务太多来不及处理时,如何拒绝任务,有4个策略
    • ThreadPoolExecutor.AbortPolicy():抛出java.util.concurrent.RejectedExecutionException异常
    • ThreadPoolExecutor.CallerRunsPolicy:直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
    • ThreadPoolExecutor.DiscardOldestPolicy():丢弃最老的任务
      -ThreadPoolExecutor.DiscardPolicy:丢弃当前任务

当通过execute提交任务执行时:

  • 如果当前线程数量小于corePoolSize,创建新的线程处理任务
  • 如果当前线程数量等于corePoolSize,任务加入workQueue队列
  • 如果线程池中数量大于等于corePoolSize,workQueue队列满,线程数量小于maximumPoolSize,创建新的线程处理任务
  • 如果线程池中线程数量等于maximumPoolSize,workQueue队列也满,根据handler指定的拒绝策略处理任务
  • 如果线程池中线程数量大于corePoolSize,空闲线程超过keepAliveTime,线程将被销毁

Executors工具类方法

newSingleThreadExecutor

//java.util.concurrent.Executors

public static ExecutorService newSingleThreadExecutor() {
		  /**
         * coolPoolSize = 1 核心线程个数1
         * maximumPoolSize = 1 最大线程个数都为 1 
         * maximumPoolSize = 0 说明只要线程个数比核心线程个数多并且当前空闲 则 回收。
         * LinkedBlockingQueue(): 最大任务数Integer.MAX_VALUE
         */
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

//自定义:threadFactory 创建
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {		
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

newFixedThreadPool

 public static ExecutorService newFixedThreadPool(int nThreads) {
 	//创建一个核心线程个数和最大线程个数都为 nThreads 的线程池
     return new ThreadPoolExecutor(nThreads, nThreads,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>());
  }
//自定义线程池--略

newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
    /**
     * 
     * @param  0                           核心线程数 1 
     * @param  Integer.MAX_VALUE           最大线程数  Integer.MAX_VALUE
     * @param  60L                          
     * @param  TimeUnit.SECONDS             最大空闲时间60s
     * @param  SynchronousQueue<Runnable>() 同步队列将任务直接提交给线程而不保持它们。
     */
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                   60L, TimeUnit.SECONDS,
                                   new SynchronousQueue<Runnable>());
 }
}

execute()–添加任务

execute方法的作用是提交任务command到线程池中进行执行。用户提交任务到线程池中的模型如下图:
在这里插入图片描述
execute()

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
     
        int c = ctl.get();


        //1.如果线程池线程数 < 核心线程数 ==== 直接添加一个核心线程,并将command作为该线程的第一个任务;  --执行成功 return ;
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }


       //2. 线程池状态 RUNNING 状态,则将command添加至 workQueue
        if (isRunning(c) && workQueue.offer(command)) {
            //任务添加成功后,二次检查
            int recheck = ctl.get();

            //如果线程不处于RUNNING状态,从队列中将任务删除
            if (! isRunning(recheck) && remove(command))
                //执行决绝策略
                reject(command);

            // ,如果当前线程池线程数为0,则新增一个线程
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //3. 当workQueue无法offer任务,则尝试新增一个worker线程,如果新增失败,则执行reject操作;
        else if (!addWorker(command, false))
            reject(command);
    }

execute创建线程分为3步:

  1. 尝试创建核心线程 – 成功 return;
  2. 尝试向任务队列(workQueue)里添加任务 – 失败,跳转至3
  3. 尝试新增worker线程

addWorker()

//增加worker
    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            //获取线程池状态(高三位)
            int rs = runStateOf(c);

        
            //1.
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;



            for (;;) {
                //获取工作线程数量
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    //core == true,表示新增线程为:核心线程
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;

                //CAS操作: 工作线程数+1
                if (compareAndIncrementWorkerCount(c))
                    break retry;

                //CAS操作失败,查看线程池状态是否发生变化.
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs) 
                    continue retry; //发生变化,调到外层循环重新执行循环


                //未发生变化,继续执行内层U型你换
            }
        }

        //CAS操作执行完毕...
     
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            //创建worker
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                //持有独占锁
                mainLock.lock();
                try {
                    // 
                    int rs = runStateOf(ctl.get());

                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // 如果线程已经启动,抛出异常
                            throw new IllegalThreadStateException();

                        //将w添加到workers
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    //释放锁
                    mainLock.unlock();
                }
                if (workerAdded) {
                    //启动线程
                    t.start();

                    //设置启动标识
                    workerStarted = true;
                }
            }
        } finally {
             //设置启动标识为false
            if (! workerStarted)
                //添加addWorkerFailed操作, 将w从workers中移除;
                addWorkerFailed(w);
        }
        return workerStarted;
    }

1.

/**
 *  `RUNNING(111 0~29)`: 接受新任务 && 处理阻塞队列里的任务。
 *  `SHUTDOWN(000 0~29)`:拒绝新任务,但是处理阻塞队列里的任务。
 *  `STOP(001 0~29)`:   拒绝新任务 && 抛弃阻塞队列里任务,同时中断正在处理的任务。
 *  `TIDYING(010 0~29)`: 所有任务都执行完成(包含阻塞队列[此时为空]),线程池活动线程数为0
 *  `TREMINATED(011 0~29)`:终止状态。
 */
if (rs >= SHUTDOWN &&
        ! (rs == SHUTDOWN &&
           firstTask == null &&
           ! workQueue.isEmpty()))
    return false;

转换为:
if (rs >= SHUTDOWN &&
         (rs != SHUTDOWN ||
           firstTask != null ||
           workQueue.isEmpty()))
    return false;

转换为:
if (rs > SHUTDOWN) 
    //当前线程池状态为 STOP 、 TIDYING 或 TERMINATED 。
    return falseif (rs == SHUTDOWN && (firstTask != null || workQueue.isEmpty())) {
    //当前线程池状态为 SHUTDOWN 并且 firstTask != null  ---- 拒绝新任务
    //当前线程池状态为 SHUTDOWN 并且任务队列为空。
    return false;
}

Worker

Worker继承了AQS,重写了一些列方法。
Worker

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        final Thread thread;
        Runnable firstTask;
        //记录当前worker,完成的任务数
        volatile long completedTasks;

   
        Worker(Runnable firstTask) {
            setState(-1); //设置state=-1, 此时不允许interrupt
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

      
        public void run() {
            runWorker(this);
        }
		
		//是否持有独占锁:state=1,表示持有
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }
		
		//尝试获取锁
        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
	
		//释放锁
        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        public void lock()        { acquire(1); }
        public boolean tryLock()  { return tryAcquire(1); }
        public void unlock()      { release(1); }
        public boolean isLocked() { return isHeldExclusively(); }

        void interruptIfStarted() {
            Thread t;
            //state>=0 时,才允许interrupt.
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                t.interrupt();
            }
        }
    }

w.thread.start()调用run(),最终调用ThreadPoolExecutor.runWorker();

runWorker()

   final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); 
        boolean completedAbruptly = true;
        try {
            //从
            while (task != null || (task = getTask()) != null) {
                //w持有锁 
                w.lock();
               
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    //异常处理(略....)
                 
                    //beforeExecute ---空实现
                    beforeExecute(wt, task);

                    task.run();
                    
                     //beforeExecute ---空实现
                     afterExecute(task, thrown);
                } finally {
                    task = null;
                    //最后completedTasks++
                    w.completedTasks++;

                    //w释放锁
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            //待任务完成之后,执行清理操作
            processWorkerExit(w, completedAbruptly);
        }
    }

processWorkerExit

 private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //统计整个线程池的 任务完成数
            completedTaskCount += w.completedTasks;

            //移除worker
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        //尝试设置为TERMINATE状态
        //如采当前是SHUTDONW状态,并且工作队列为空
        //或者当前是STOP状态 ,当前线程池里面没有活动线程
        tryTerminate();

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; 
            }
            //如果workQueue队列不为空 && 线程数< 核心线程数, 则增加线程
            addWorker(null, false);
        }
    }

shutdown()

执行shutdown()方法后,线程池就不再接受新的任务了,但是workQueue中的任务还是要执行的。

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //1.权限检查
            checkShutdownAccess();

            //2.尝试将状态设置为SHUTDOWN,若当前状态>=SHUTDOWN,则直接返回;
            advanceRunState(SHUTDOWN);

            //3. 中断idle的workers ----- 正在执行的线程不会被中断.
            interruptIdleWorkers();

            //ScheduledThreadPoolExecutor的钩子函数,在这里为空实现;
            onShutdown(); 
        } finally {
            mainLock.unlock();
        }

        //4.尝试设置为TERMINATE状态.
        tryTerminate();
    }

shutdownNow()

调用shutdownNow()方法后,线程池不再接受新的任务,并丢失任务队列中的任务,正在执行的任务会被中断,该方法会立即返回。返回值为队列里被丢弃的任务列表。

 public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();

            //线程池状态设置为STOP
            advanceRunState(STOP);

            //中断所有worker线程 ----- 正在执行的线程依然会被中断
            interruptWorkers();

            //将workQueue中的任务移动至tasks列表;
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

总结

线程池巧妙地使用一个 Integer 类型的原子变量来记录线程池状态和线程池中的线程个数。
通过线程池状态来控制任务的执行,每个 Worker 线程可以处理多个任务。
线程池通过线程的复用减少了线程创建和销毁的开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值