java并发-线程池源码分析

360 阅读13分钟

Executor

Executor是线程池组件的顶层接口
只是定义了一个方法:
void execute(Runnable command);

有如下三个子类比较重要:
1. ExecutorService 继承 Executor接口
2. AbstractExecutorService 继承 ExecutorService接口
3. ThreadPoolExecutor 继承了 AbstractExecutorService抽象类

创建线程池

Executors是线程池工具类提供了如下创建线程池的方法

Executors是线程池工具类提供了如下创建线程池的方法

看了如下的静态方法,会发现都是使用的ThreadPoolExecutor的构造方法,只不过jdk帮助我们写死了部分操作参数

ThreadPoolExecutor 也是我们日常开发中 最常用的类,所有我们主要要看 ThreadPoolExecutor

Executors.newSingleThreadExecutor();

//创建一个单一线程的线程池
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

Executors.newFixedThreadPool(30);

//创建一个固定数量线程的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

Executors.newCachedThreadPool();

//创想一个可变数量线程的线程池
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

ThreadPoolExecutor基础信息

//找到最全参数的一个构造方法看一下
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

//从代码中我们发下这个构造方法就是一些简单的赋值,我们主要看下这些参数的含义

ThreadPoolExecutor 构造方法参数含义

1. corePoolSize : 线程池中所一直维护的线程数量,如果线程池处于任务空闲期间,那么这些线程也不会被回收掉
2. maximumPoolSize : 线程池中所维护的线程最大数量
3. keepAliveTime  : 超过了corePoolSize的线程在经过keepAliveTime时间后如果一直处于空闲状态,那么这些超过的线程要被回收掉
4. unit : 时间单位
5. workQueue : 向线程池所提交的任务位于的阻塞队列,他的实现有多种方式
6. threadFactory : 线程工工厂,用于创建新的线程并被线程池所管理,默认线程工厂所创建的线程都是用户线程且优先级为5
7. handler : 表示当前线程池中的线程都在执行任务并且等待队列也满了,那么对于新来的任务的拒绝策略,有如下四种

threadFactory
threadFactory就是给这个线程池创建线程的
假如你不实现使用的默认工厂 DefaultThreadFactory
DefaultThreadFactory
//主要看下newThread方法 , newThread 就是给线程池创建线程的方法

public Thread newThread(Runnable r) {
	//创建线程 拼接线程的名称
    Thread t = new Thread(group, r,
                          namePrefix + threadNumber.getAndIncrement(),
     // 假如是守护线程,设置为普通线程
     // 这也就是为啥我们需要手动关闭 线程池的原因
    if (t.isDaemon())
        t.setDaemon(false);
    if (t.getPriority() != Thread.NORM_PRIORITY)
        t.setPriority(Thread.NORM_PRIORITY);
    return t;
}
handler(拒绝策略) RejectedExecutionHandler
拒绝策略,有如下四种:
1. AbortPolicy    直接抛出运行时异常
2. DiscardPolicy  直接丢弃掉任务,就是空实现,也不抛出异常
3. DiscardOldestPolicy 丢弃阻塞队列中最早的一个任务,并且为当前所提交的任务留出一个队列中的位置,以便将其放入队列中
4. CallerRunsPolicy  直接在提交任务的线程上执行 ,  就是 直接调用了  run 方法 
5.也可以自定义处理
AbortPolicy
public static class AbortPolicy implements RejectedExecutionHandler {
    
    public AbortPolicy() { }

    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    	// 直接抛出异常
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}

DiscardPolicy
public static class DiscardPolicy implements RejectedExecutionHandler {
    
    public DiscardPolicy() { }

    // 啥也不做,就是相当于把这个任务丢弃掉了
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}
DiscardOldestPolicy
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    
    public DiscardOldestPolicy() { }

    
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
        	// 移除队列中的第一个元素
            e.getQueue().poll();
            //把新的任务 调用 execute 方法
            e.execute(r);
        }
    }
}
CallerRunsPolicy
public static class CallerRunsPolicy implements RejectedExecutionHandler {
    
    public CallerRunsPolicy() { }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    	//假如线程池的状态是正常的
        if (!e.isShutdown()) {
        	// 直接运行这个任务run()   那就相当于是  操作线程池提交任务的线程在执行这个 runnable
            r.run();
        }
    }
}

ThreadPoolExecutor 执行方法

ThreadPoolExecutor执行方法有如下四个:
1. <T> Future<T> submit(Callable<T> task)    ExecutorService提供的抽象方法,AbstractExecutorService中实现
2. <T> Future<T> submit(Runnable task, T result)    ExecutorService提供的抽象方法,AbstractExecutorService中实现
3. Future<?> submit(Runnable task);     ExecutorService提供的抽象方法,AbstractExecutorService中实现
4. void execute(Runnable command)   Executor接口提供的抽象方法,ThreadPoolExecutor实现

submit(Callable< T > task)

//处理任务 返回一个 Future<T> 

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    //封装为一个 RunnableFuture 见名知意  这个接口既是个runnable又是个Future
    //submit 三种重载的方法都是使用的 RunnableFuture 所有看下这个类 和 newTaskFor 方法
    RunnableFuture<T> ftask = newTaskFor(task);
    //调用 Executor 接口的 execute 方法  (重要)
    execute(ftask);
    return ftask;
}

RunnableFuture (有兴趣的可以看,不影响整体流程)

//这个是接口,定义如下:
// 即继承了 Runnable 接口 , 又继承了 Future接口 
// 即是任务 又是  结果
public interface RunnableFuture<V> extends Runnable, Future<V> {
  /**
   * Sets this Future to the result of its computation
   * unless it has been cancelled.
   */
  void run();
}

// 线程池中使用的实现类 叫做 FutureTask  

newTaskFor -- FutureTask (有兴趣的可以看,不影响整体流程)

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}
//newTaskFor 方法还有一个重载的方法  ,  就是在 submit 的另外两种重载方法会使用 
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}



//这个方法就不说了比较清晰,只要知道 最后执行这个de 是 Executor.execute(Runnable) 
// FutureTask 顶层 也实现了 Runnable , 所有能执行 , 先执行 FutureTask.run() ,run方法中有调用了FutureTask.call方法,返回结果就是Callable具体返回的值
//这个总结下执行流程是   execute -> run -> call
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    // 就是简单的赋值  
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

// 构造器  对应着传递 Runnable 类型
public FutureTask(Runnable runnable, V result) {
	// 这里是把 Runnable 封装为 Callable
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}

//适配器
//内部类 , 本身继承 Callable,有个成员变量Runnable
static final class RunnableAdapter<T> implements Callable<T> {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task, T result) {
        this.task = task;
        this.result = result;
    }
    public T call() {
    	//调用run 
        task.run(); 
        //返回结果就是 传递进来的 result
        return result;
    }
}

//总结出 加过传递的是 runnable 执行流程: execute -> run -> call -> run


submit(Runnable< T > task)

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    // 这个上面都已经说了下 又兴趣的可以去看看  
    // 这个 ftask.get()  获取的结果是 null  因为方法传递的结果就是null
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    //调用execute
    execute(ftask);
    return ftask;
}

submit(Runnable task, T result)

public <T> Future<T> submit(Runnable task, T result) {
    if (task == null) throw new NullPointerException();
    // 和上一个方法一样  ,  就是传递了 ftask.get() 一个结果  
    RunnableFuture<T> ftask = newTaskFor(task, result);
    //调用execute
    execute(ftask);
    return ftask;
}

线程池的执行流程

由上面的3个submit方法可以看出都是调用了execute方法,所以这是我们的重点
关于线程池的总体执行策略:
1..如果线程池中正在执行的线程数小于corePoolSize,那么线程池就会优先创建新的线程而不是将提交的任务放到阻塞队列中
2..如果线程池中正在执行的线程数大于或者等于corePoolSize,那么线程池会优先选择对提交的任务进行阻塞排队,而不是创建新的线程
3..如果提交的任务无法添加到阻塞队列中,那么线程池就会创建新的线程,如果创建的线程数超过了maximumPoolSize,那么就会触发拒绝策略

线程池存在5中状态:
1..RUNNING   : 表示线程池可以接受新的任务的提交,并可以正常处理阻塞队列中的任务
2..SHUTDOWN  : 表示线程池不在接受新的任务的提交,但是可以处理阻塞队列中的任务
3..STOP		  :  表示线程池不再接受新的任务,同时还会丢弃阻塞中的任务,还会中断正在这个执行的任务
4..TIDYING   : 表示线程池中所有的任务都执行完毕后,当前线程中的活性的线程数降为0,将会调用terminated()
5..TERMINATED: 表示线程池的终止状态
关于线程池的有一些问题
1. 核心线程数是如何保持的 
-- getTask()方法中从 workQueue 中获取任务的时候,根据 allowCoreThreadTimeOut(是否使用超时时间处理核心线程) 
||
当前线程数量>核心线程数(由此可见大于核心线程数的会被回收)

2. 在任务执行之前打印日志
-- 在runWorker方法中存在 beforeExecute,afterExecute方法,如果需要可以在子类中实现

3. 核心线程会不会发生变化
-- 当线程执行异常时,会有补偿机制,创建新的线程替换

4. 超过keepAliveTime时间之后如何回收线程
-- 参考问题1


//能保证原子性的 ctl 
//高3为 线程池的状态  其余的29位 为创建的线程数,也就是说一个线程池最多可以创建 2 的 29 次方 的数量(硬件支撑的主的话)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1; // 这玩意为 29 个 1 ,主要是为了下面的运算符操作的

// runState is stored in the high-order bits
//这些线程池的状态,不要纠结他们的十进制说了 ,只看高3位就行了 
//例如STOP 这个状态转化为 二进制为 :  100000000000000000000000000000
private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

// Packing and unpacking ctl
//当前的线程池状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//工作线程个数
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }


public void execute(Runnable command) {
	// 任务为空,直接抛异常
    if (command == null)
        throw new NullPointerException();
    //获取 ctl 
    int c = ctl.get();
    //这个判断为:
    //判断当前工作的线程(存在的线程)是否大于 核心线程数
    if (workerCountOf(c) < corePoolSize) {
    	//假如不大于 添加一个线程 注意addWorker 方法的第二个参数为 true
        //这段代码验证了上面提到的流程 1 
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //假如走到这里 , 说明是存在的线程大于核心线程池
    //isRunning 是判断当前线程池的状态是否正常
    //假如线程池的状态正常为RUNNING,那么添加任务到等待队列 也就是 workQueue.offer(command)
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        //假如这个时候 线程池的状态不正常了 , 那就删除这个任务
        if (! isRunning(recheck) && remove(command))
        	//并执行拒绝策略
            reject(command);
         //这个是判断当前 还有没有可用的线程    
        else if (workerCountOf(recheck) == 0)
        	// 没有了就添加一个  addWorker 第二个参数为false
            addWorker(null, false);
    }
    // 走动这里就是说明  , 现在存在的线程数大于 corePoolSize , 并且阻塞队列中也都加满了
    //所以这个时候 继续创建线程 , addWorker 的第二个参数为 false
    else if (!addWorker(command, false))
    	// 假如失败  执行拒绝策略
        reject(command);
}

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 并且后面表达式中的有最少一个不成立  这个if运算的结果都是 true 创建工作线程失败
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
            int wc = workerCountOf(c);
            //判断工作线程是否满了
            // 上面的那个方法 我一直提的 当前方法的第二个参数 
            // 假如是true 是和 corePoolSize,false 是个 maximumPoolSize 比较
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
                // CAS 递增 工作线程的个数
            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;
    //创建线程添加到工作 set 中成功 标志位
    boolean workerAdded = false;
    Worker w = null;
    try {
    	// 创建了工作线程
        // Worker 这个类会在后面将,主要的工作都是在  Worker 中
        // 现在只要知道 Worker 是个 Runnable ,里面有个创建的线程就行
        w = new  Worker(firstTask);
        //获取创建的线程
        final Thread t = w.thread;
        if (t != null) {
            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());
				// 检查线程池的状态
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    //把这个 Worker 添加到 workers
                    workers.add(w);
                    int s = workers.size();
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                        //修改标志位
                    workerAdded = true;
                }
            } finally {
            //释放锁
                mainLock.unlock();
            }
            if (workerAdded) {
            	//执行线程 也就是 worker 的run 
                //所以 Worker 这个类的 run()  是下面的重点 
                t.start();
                workerStarted = true;
            }
        }
    } finally {
    	//假如失败  , 处理操作 不看了
        if (! workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}

Worker

class定义

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
        
实现了Runnable
继承了AQS

Worker构造方法

//参数为我们提交的任务
Worker(Runnable firstTask) {
	// 这个设置 state 是为了防止线程被中断
    setState(-1); // inhibit interrupts until runWorker
    //将我们提交的任务 赋值到 自己的 firstTask 属性上,,, 注意,当前Worker 也是 Runnable 的实例,存在run方法,别搞混了
    this.firstTask = firstTask;
    //使用 线程工厂 创建新的线程, 是将当前自己的实例放入的 Thread 而不是我们提交的 Runnable (注意)
    this.thread = getThreadFactory().newThread(this);
}

Worker.run()

public void run() {
    runWorker(this);
}


final void runWorker(Worker w) {
	//获取到创建的线程 , 注意  现在这个线程是启动的  在 addWorker方法中启动的
    Thread wt = Thread.currentThread();
    //获取我们提交的任务
    Runnable task = w.firstTask;
    //把 Worker  里面的 Runnable类型的属性设置为 null,因为这个线程执行完这个任务还要去执行别的任务,防止重复执行
    w.firstTask = null;
    w.unlock(); // allow interrupts
    
    //这个表示是否出错  true 表示存在问题
    boolean completedAbruptly = true;
    try {
    	// 这行代码的意思是
        //1.假如创建这个 Worker 的时候 提交了任务,那么就执行
        //没有提交 或者 是已经执行完了提交的任务 从阻塞队列中去拿任务 (这个任务 就是在execute 方法中添加的)
        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
            //看下线程池的状态 假如是 STOP 或者 下面的一串都成立,中断当前线程
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
            	//空实现
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                	// 执行我们提交的Runnable 的 run
                    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);
    }
}


//大致流程就这样吧,还有些没整明白的后面补