android 线程池源码分析

一直觉得这块比较复杂,原因在于需要对数据结构和多线程开发比较熟悉。现在从ThreadPoolExecutor 出发。先看这个构造函数。

public ThreadPoolExecutor(int corePoolSize,
                            int maximumPoolSize,
                            long keepAliveTime,
                            TimeUnit unit,
                            BlockingQueue<Runnable> workQueue) {
      this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
           Executors.defaultThreadFactory(), defaultHandler);
  }

来看看这个执行线程的方法吧。

   public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
         //获取WorkerThread的线程数,这个是整数原子变量。
        int c = ctl.get();
        //如果工作线程数量小于corePoolSize,那么addWorker。
        if (workerCountOf(c) < corePoolSize) {
        //如果addWork成功直接返回了。
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //如果工作线程已经超过corePoolSize了,workQueue 属于阻塞队列。会一直阻塞加入wokrQueue队列。
        //这个workQueue是四大线程池不同的地方也是关键。当任务已满,会阻塞,超时取消。
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            //如果没有正在运行,并且移除成功了那么拒绝策略
            if (! isRunning(recheck) && remove(command))
                reject(command);
            //如果工作线程数量为0,则启动一非核心线程。到这里为止,已经不能启动核心线程了。    
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //添加非核心线程。如果不成功则执行拒绝策略。
        else if (!addWorker(command, false))
            reject(command);
    }

看下关键方法,addWorker。看这个之前补充一个方法。补充一点线程池的知识

//代表线程池的数量最大位占据2^29。
 private static final int COUNT_BITS = Integer.SIZE - 3;
 //从0开始计数那么最大整数值应该就是2^29-1.
   private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
//这里分析下CAPACITY 的二进制。00001111.......1,int第一位为符号为。~CAPACITY为
// 11110000.....0。

   //线程池状态变量。Running为-(2^29)。负值的二进制为正值取反+1。(计算机中最高位为符号位,绝对值用补码表示)2^29 值为 000100000..0 那么Running 的二进制应该为1110 0000.....1。
   private static final int RUNNING    = -1 << COUNT_BITS;
   //SHUTDOWN的二进制为 00000000......0。aka 0
   private static final int SHUTDOWN   =  0 << COUNT_BITS;
   //STOP的二进制为0001000..  0
   private static final int STOP       =  1 << COUNT_BITS;
   //TIDYING的二进制为0010..0
   private static final int TIDYING    =  2 << COUNT_BITS;
   //TERMINATED  二进制为 0011...0。
   private static final int TERMINATED =  3 << COUNT_BITS;

   // Packing and unpacking ctl
   //如果随意一个整数我要求出它的state值,那么如何求呢?比如我取 c=000101010101000010...0。
   //  ~CAPACITY 为11110000.....0,那么c& ~CAPACITY=0001000000000==STOP。实际判断的是除开符号位的,高三位的值。RUNNING 我110,SHUTDOWN 为000,STOP为001,TIDYING为010,TERMINATED 为011,
   private static int runStateOf(int c)     { return c & ~CAPACITY; }
 // 低29位存储的是线程数量。CAPACITY 为00001111.......1。c&CAPACITY 正好等于低29位值。
 //这段比较啰嗦可能以为位运算给人的直观性不强,所以细致分析了。  
   private static int workerCountOf(int c)  { return c & CAPACITY; }
   private static int ctlOf(int rs, int wc) { return rs | wc; }
 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //rs>=SHUTDOWN,代表不是RUNNING。if里面可理解为两个条件同时成立,那么不允许添加worker,
            //(线程)。如果线程池不是running状态。因为running状态是个负值。另外一个条件是。rs!=SHUTDOWN,firstTask 不等于空,并且工作线程队列不为空,这种情况下不允许添加。
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
                           
            for (;;) {
            //计算工作线程数量。
                int wc = workerCountOf(c);
            //如果大于线程容量,或者核心线程数量大于最大的核心线程数量直接返回。如果工作线程大于核心线程也是不能够再增加线程的。    
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                //增加线程数量+1。如果成功跳出循环。    
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
      
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
        //构造Worker,一个work对应一个thread。  
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
            //同步非公平锁。之前已经分析过ReentrantLock 原理。
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());
                     //rs<SHUTDOWN,代表Running状态。或者即时是SHUTDOWN,但是任务为空,也允许添加。
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                       //增加到workers里面。Workers 是一个存储Wokk的HashSet。     
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                //如果添加成功,则执行start,实际调用的是Work的run,最终执行的是我们的Runnable。
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

现在在分析下shutdown() 逻辑。

  public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
        // 检查是否有关闭的权限。
            checkShutdownAccess();
        //     
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

//更新 线程池的标志SHUTDOWN or STOP。

   private void advanceRunState(int targetState) {
        // assert targetState == SHUTDOWN || targetState == STOP;
        for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

//循环遍历work,当然先记得先上锁。

 private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                //w.tryLock 是代表这个t线程上锁。
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                     //中断 。
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

这里还有个逻辑没有完,那就是Work里面的run方法。
runWorker属于启动线程的操作了,task只是一个Runnable。

 final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        //看到了没,firstTask一旦执行完毕立即置空。
        Runnable task = w.firstTask;
        w.firstTask = null;
        //先解锁。
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
        //看到了没,这个逻辑至关重要,因为getTask()会从WorkQueue拿到Runnable。如果你传一个空的任务,
        //但是你确开启了一个线程去执行workqueue的任务,从这个地方体现了工作线程和非工作线程都能够执行任务的逻辑。
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                //检查多线程操作。代码的难点主要是为了管理多线程。
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                //钩子方法。
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                    //开始执行。
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值