ThreadPoolExecutor源码初探

Posted TellH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreadPoolExecutor源码初探相关的知识,希望对你有一定的参考价值。

重要的类或成员

ctl

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

ThreadPoolExecutor用这一个原子整型变量保存了两个内容:

  • 所有有效线程的数量
  • 各个线程的状态(runState)

低29位存线程数,高3位存runState(线程池的运行状态),这样runState有5个值:

  • RUNNING:-536870912
  • SHUTDOWN:0
  • STOP:536870912
  • TIDYING:1073741824
  • TERMINATED:1610612736

Worker

private final class Worker extends AbstractQueuedSynchronizer implements Runnable

Worker是ThreadPoolExecutor的静态内部类,主要是对Thread对象的包装,一个Worker内部有一个Thread对象。同时Worker继承自AQS来实现一个简单互斥锁,每一个任务的执行前和执行后都会分别获取和释放一次锁。(acquiring and releasing a lock surrounding each task execution)这样做是为了让线程执行任务时屏蔽中断操作。

那么为什么不用ReentrantLock呢?其实是为了避免在任务执行中修改线程池的变量和状态,不能用可重入锁。

execute

execute(Runnable command)

    public void execute(Runnable command) 
        int c = ctl.get(); // 获取线程池的状态
        if (workerCountOf(c) < corePoolSize)  // 如果当前工作线程数小于所配置的核心线程数
            if (addWorker(command, true)) // 新建一个工作线程作为核心线程,并把该任务交给它执行
                return;
            c = ctl.get();
        
        if (isRunning(c) && workQueue.offer(command))  // 往等待队列添加任务
          // double-check
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        
        else if (!addWorker(command, false)) // 开辟一个线程执行该任务
            reject(command);
    

addWorker

    private boolean addWorker(Runnable firstTask, boolean core) 
      ...
        Worker w = null;
        try 
            w = new Worker(firstTask);// 参见1#.
            final Thread t = w.thread;
            if (t != null) 
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try 
                  ...
                        workers.add(w); // workers是一个HashSet,一个工作线程的集合
                  ...
                 finally 
                    mainLock.unlock();
                
                if (workerAdded) 
                    t.start(); // 参见2#.
                    workerStarted = true;
                
            
         finally 
            if (! workerStarted)
                addWorkerFailed(w);
        
        return workerStarted;
    

1#. 创建Worker对象,同时通过线程工厂创建一个新的线程

        Worker(Runnable firstTask) 
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
          // this是指Worker对象,它将作为Thread的Runnable target
            this.thread = getThreadFactory().newThread(this); 
        

2#. 启动Worker线程,由于Worker也是一个Runnable对象,在Worker线程启动之后,Worker的run方法会被调用

        /** Delegates main run loop to outer runWorker  */
        public void run() 
            runWorker(this); //Worker线程开始工作啦
        

runWorker(Worker w)

ThreadPoolExecutor#runWorker会开启worker线程的任务执行循环。

    final void runWorker(Worker w) 
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        try 
            while (task != null || (task = getTask()) != null)  // 参见1.
                w.lock(); // 开始执行任务前加锁,屏蔽中断
              ...
                try 
                    beforeExecute(wt, task);
                  ...
                    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);
        
    
  1. getTask()方法会从任务队列中取任务,如果工作队列没有任务则工作线程会被阻塞直到被生产者唤醒。
    private Runnable getTask() 
    ...
        for (;;) 
            ...
            try 
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take(); // 从任务等待队列中取任务
              ...
             catch (InterruptedException retry) 
                timedOut = false;
            
        
    

调用时序

总结

ThreadPoolExecutor作为最基础的线程池,提供了多个可配置参数,如核心线程数,最大线程数,线程超时销毁,线程工厂,任务等待队列,拒绝策略等,方便开发者基于此做各种灵活的定制。

ThreadPoolExecutor利用BlockingQueue实现了典型的生产者和消费者模型,为Java开发者提供了优秀的范本。

以上是关于ThreadPoolExecutor源码初探的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程:ThreadPoolExecutor初探

JAVA 笔记 ThreadPoolExecutor 源码剖析

ThreadPoolExecutor解析-部分源码研究

ThreadPoolExecutor源码阅读心得

Java多线程 -- JUC包源码分析11 -- ThreadPoolExecutor源码分析

线程池源码分析-ThreadPoolExecutor