线程池源码

线程池源码系列

一、接口层次

  • Executor
  • ExecutorService
  • AbstractExecutorService
  • ThreadPoolExecutor
  • ForkJoinPool
  • ScheduleExecutorService
  • ScheduleThreadPoolExecutor
  • Executors 线程池工具类
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yzg9c7Nr-1633849989833)(.ThreadPoolExecutor.assets1624024421050.png)]

二、Executor

public interface Executor {
   
    // 执行任务方法
    void execute(Runnable command);
}

三、ExecutorSerivce

对父接口进行了功能扩展

  • 控制线程池的操作
  • 提交任务的操作
  • 支持有返回值的任务
  • 执行多个和任意任务的操作
public interface ExecutorService extends Executor {
   
    // 关闭线程池
    void shutdown();
    // 立即关闭线程池
    List<Runnable> shutdownNow();
    // 线程池是否已关闭
    boolean isShutdown();
    // 线程池是否已销毁
    boolean isTerminated();
    // 等待线程池销毁 timout + unit
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;
    // 提交任务的方法 Callable 有返回值的任务
    <T> Future<T> submit(Callable<T> task);
    // 提交任务的方法 Runnable + result 也支持返回值
    <T> Future<T> submit(Runnable task, T result);
    // 提交 Runnable 无返回值
    Future<?> submit(Runnable task);
    // 执行所有的任务
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
    // 执行所有的任务 + 超时时间限制
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;
    // 执行任意一个任务
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;
    // 执行任意一个任务 + 超时时间限制
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

四、AbstractExecutorService

实现基本的方法

  • 提供模板方法
  • 具体的执行方法逻辑
1、创建任务 RunnableFuture 任务 -> FutureTask
// 接受 Runnable 任务 + T 的返回值类型
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
   
    return new FutureTask<T>(runnable, value);
}
// 接受 Callable 任务(自带返回值)
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
   
    return new FutureTask<T>(callable);
}
2、提交任务
// 提交 Runnable 任务
public Future<?> submit(Runnable task) {
   
    // 基本判空
    if (task == null) throw new NullPointerException();
    // 创建任务 FutureTask
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    // 执行任务
    execute(ftask);
    // 返回 FutureTask
    return ftask;
}
// 提交 Runnable + T 返回值的任务
public <T> Future<T> submit(Runnable task, T result) {
   
    // 基本判空
    if (task == null) throw new NullPointerException();
    // 创建任务 FutureTask
    RunnableFuture<T> ftask = newTaskFor(task, result);
    // 执行任务
    execute(ftask);
    // 返回 FutureTask
    return ftask;
}
// 提交 Callable 任务
public <T> Future<T> submit(Callable<T> task) {
   
    // 基本判空
    if (task == null) throw new NullPointerException();
    // 创建任务 FutureTask
    RunnableFuture<T> ftask = newTaskFor(task);
    // 执行任务
    execute(ftask);
    // 返回 FutureTask
    return ftask;
}
3、执行任务 - 执行全部任务
// 不带超时时间的执行所有任务 - 一定要执行完全部,除非出现异常
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
    throws InterruptedException {
   
    // 基本判空
    if (tasks == null)
        throw new NullPointerException();
    ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
    // 标志位 - 是否全部完成
    boolean done = false;
    try {
   
        // 循环创建任务,并将任务执行,获取到异步执行的任务 futures
        for (Callable<T> t : tasks) {
   
            RunnableFuture<T> f = newTaskFor(t);
            futures.add(f);
            execute(f);
        }
        // 循环等待所有任务执行完成
        for (int i = 0, size = futures.size(); i < size; i++) {
   
            Future<T> f = futures.get(i);
            // 当前任务没有完成就调用 get 阻塞等待
            if (!f.isDone()) {
   
                try {
   
                    f.get();
                    // 这里如果我们的任务出现异常,那么会抛出,程序将中断 -> 跳转到 finally 块
                } catch (CancellationException ignore) {
   
                } catch (ExecutionException ignore) {
   
                }
            }
        }
        // 所有任务正常执行完成设置标志位 true,表示全部执行完成
        done = true;
        // 返回我们的结果
        return futures;
    } finally {
   
        // 如果没有被设置 true,表示任务没有完全被执行完,也即出现了异常情况
        if (!done)
            // 拿到任务,依次取消掉任务,当然已经完成的任务取消是没有效果的
            // 详情见 FutureTask
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
    }
}
4、执行任务 - 带超时时间执行全部任务
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                     long timeout, TimeUnit unit)
    throws InterruptedException {
   
    // 基本判空
    if (tasks == null)
        throw new NullPointerException();
    // 时间转换为 纳秒 单位
    long nanos = unit.toNanos(timeout);
    // 异步执行的任务集合
    ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
    // 一样的全部任务完成的标准位
    boolean done = false;
    try {
   
        // 为了不影响计时出现偏差,这里先把所有的任务创建好
        for (Callable<T> t : tasks)
            futures.add(newTaskFor(t));
        // 截至时间
        final long deadline = System.nanoTime() + nanos;
        final int size = futures.size();
        // 执行任务
        for (int i = 0; i < size; i++) {
   
            execute((Runnable)futures.get(i));
            nanos = deadline - System.nanoTime();
            // 检查是否超时,超时直接返回,这里返回的任务就有可能没有执行的任务
            if (nanos <= 0L)
                return futures;
        }
        // 循环等待任务执行完成
        for (int i = 0; i < size; i++) {
   
            Future<T> f = futures.get(i);
            // 任务没有完成
            if (!f.isDone()) {
   
                // 再次超时检查,超时直接退出
                if (nanos <= 0L)
                    return futures;
                try {
   
                    // 超时阻塞等待
                    f.get(nanos, TimeUnit.NANOSECONDS);
                } catch (CancellationException ignore) {
   
                } catch (ExecutionException ignore) {
   
                } catch (TimeoutException toe) {
   
                    // 超时异常直接返回异步执行的任务 - 存在未完成的异步任务
                    return futures;
                }
                nanos = deadline - System.nanoTime();
            }
        }
        // 全部执行完成,返回异步执行的任务 - 全部都已经执行完成的
        done = true;
        return futures;
    } finally {
   
        // 同理,没有全部执行完成-超时或出现了异常
        if (!done)
            // 依次取消任务 - 已完成的不会有影响
            // 详情见 FutureTask
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
    }
}
5、执行任务 - 执行任意一个任务
// 执行任意一个任务
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
    throws InterruptedException, ExecutionException {
   
    try {
   
        return doInvokeAny(tasks, false, 0);
    } catch (TimeoutException cannotHappen) {
   
        assert false;
        return null;
    }
}
// 带超时时间的执行任意一个任务
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                       long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException {
   
    return doInvokeAny(tasks, true, unit.toNanos(timeout));
}
// 具体的执行方法
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                          boolean timed, long nanos)
    throws InterruptedException, ExecutionException, TimeoutException {
   
    // 基本判空
    if (tasks == null)
        throw new NullPointerException();
    // 任务大小
    int ntasks = tasks.size();
    // 任务数为0的情况,抛异常
    if (ntasks == 0)
        throw new IllegalArgumentException();
    // 异步执行的任务集合
    ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
    // ExecutorCompletionService -> 将当前线程池 this 传入其内部
    ExecutorCompletionService<T> ecs =
        new ExecutorCompletionService<T>(this);
    try {
   
        // 记录异常
        ExecutionException ee = null;
        // 超时时间
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        // 拿到任务迭代器
        Iterator<? extends Callable<T>> it = tasks.iterator();
        // next() 拿到第一个任务丢给 ExecutorCompletionService,内部对任务进行二次封装
        futures.add(ecs.submit(it.next()));
        // 任务数量 -1
        --ntasks;
        // 正在执行的任务数量 +1
        int active = 1;
        // 死循环
        for (;;) {
   
            // 任务执行完成时或任务取消时,会将任务丢到 ExecutorCompletionService 的队列中
            // 如果任务没有完成,那么 poll()方法返回的就是 null
            Future<T> f = ecs.poll();
            // 这里表示任务没有完成
            if (f == null) {
   
                // 还有任务
                if (ntasks > 0) {
   
                    // 任务数量 -1
                    --ntasks;
                    // 拿到下一个任务继续
                    futures.add(ecs.submit(it.next()));
                    // 正在执行的任务数量 +1
                    ++active;
                }
                // 如果正在执行的任务为 0 了,表示执行完了,执行 break退出循环
                else if (active == 0)
                    break;
                // 如果是带超时的情况,检查是否超时
                else if (timed) {
   
                    // 超时获取执行结果
                    f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                    // 没有拿到结果,表示超时了
                    if (f == null)
                        throw new TimeoutException();
                    nanos = deadline - System.nanoTime();
                }
                // 如果其他情况都不满足 - take 方法获取会抛异常
                else
                    f = ecs.take();
            }
            // 如果有执行完成的任务
            if (f != null) {
   
                // 正在执行的任务数量 -1
                --active;
                try {
   
                    // 拿到执行的结果返回
                    return f.get();
                } catch (ExecutionException eex) {
   
                    ee = eex;
                } catch (RuntimeException rex) {
   
                    ee = new ExecutionException(rex);
                }
            }
        }
        if (ee == null)
            ee = new ExecutionException();
        throw ee;
    } finally {
   
        // 取消其他没有执行完成的任务,已完成的任务没有影响
        for (int i = 0, size = futures.size(); i < size; i++)
            futures.get(i).cancel(true);
    }
}

五、ThreadPoolExecutor

0、Why
1. 传统方式
  • 传统使用多线程方式
  • 继承 Thread,重写 run 方法
  • 实现 Runnable 重写 run 方法
  • 实现 Callable 重写 call 方法
  • 传统方式的弊端
  • 线程是宝贵的系统资源,频繁创建,执行完就销毁,浪费系统资源
  • 线程数量不可控,来一个任务就创建一个线程
  • 不支持定时、定期任务执行
2. 线程池方式
  • 线程池优点
  • 管理线程,线程数量可控,线程重用,提升性能
  • 支持任务挤压 - 阻塞队列存放任务
  • 支持定时执行、周期执行任务
  • 线程池要求
  • 使用者需要对线程池运行原理有足够的了解
  • 使用者需要了解不同线程池的应用场景及其正确使用方式
1、How to use
public static void main(String[] args) throws InterruptedException {
   
    ThreadPoolExecutor executor = 
        new ThreadPoolExecutor( 2,
                               5, 
                               60, 
                               TimeUnit.SECONDS,
                               new LinkedBlockingQueue<>(3));
    // 提交 8 个任务
    for (int i = 0; i < 8; i++) {
   
        executor.submit(() -> {
   
            System.out.println(Thread.currentThread().getName());
        });
    }
    executor.shutdown();
    executor.awaitTermination(100,TimeUnit.SECONDS);
}
2、线程池组件推理
  • 线程容器 - 存放线程 HashSet workers
  • 核心线程 - corePoolSize
  • 临时线程 - (maximumPoolSize - corePoolSize)
  • 临时线程存活时间 - long keepAliveTime
  • 时间单位 - TimeUnit unit
  • 任务队列 - 存放任务 - BlockingQueue workQueue
  • 线程工厂 - 创建线程 - ThreadFactory threadFactory
  • 拒绝策略 - 任务满了的解决方案 - RejectedExecutionHandler handler
ThreadPoolExecutor(int corePoolSize,
                  int maximumPoolSize,
                  long keepAliveTime,
                  TimeUnit unit,
                  BlockingQueue<Runnable> workQueue,
                  ThreadFactory threadFactory,
                  RejectedExecutionHandler handler)
3、线程池工作原理
  • 第一次提交任务到线程池,创建核心线程处理任务,直到线程数量达到 corePoolSize 核心线程数
  • 持续提交任务到线程池,此时将任务存放到任务队列 workQueue 中 ,直到任务队列满了
  • 继续提交任务,此时将创建临时线程任务处理,直到线程数量达到 maximumPoolSize 最大线程数
  • 此时任务队列满了、线程数达到最大值了如果继续提交任务,那么线程池将启用拒绝策略来拒绝任务,默认提供了四种拒绝策略
  • 随着时间的推移,任务越来越少,那么线程池将根据设置的 keepAliveTime 、unit 进行销毁线程,直到销毁的线程数量达到 corePoolSize 为止
4、线程池工厂
public interface ThreadFactory {
   
    // 创建线程
    Thread newThread(Runnable r);
}
5、四大拒绝策略 - RejectedExecutionHandler
// ① 直接抛异常
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());
    }
}
// ② 调用者执行任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
   
    public CallerRunsPolicy() {
    }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
   
        if (!e.isShutdown()) {
   
            r.run();
        }
    }
}
// ③ 抛弃当前提交的任务
public static class DiscardPolicy implements RejectedExecutionHandler {
   
    public DiscardPolicy() {
    }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
   
    }
}
// ④ 抛弃最早提交的任务
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
   
    public DiscardOldestPolicy() {
    }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
   
        if (!e.isShutdown()) {
   
            // 任务队列队头任务弹出抛弃
            e.getQueue().poll();
            // 尝试执行新任务
            e.execute(r);
        }
    }
}
6、阻塞队列 BlockingQueue - 多线程安全
// 增删改查
public interface BlockingQueue<E> extends Queue<E> {
   
  boolean add(E e);
  boolean offer(E e);
  void put(E e) throws InterruptedException;
  boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException;
  E take() throws InterruptedException;
  E poll(long timeout, TimeUnit unit)
   throws InterruptedException;
  int remainingCapacity();
  boolean remove(Object o);
  public boolean contains(Object o);
  int drainTo(Collection<? super E> c);
  int drainTo(Collection<? super E> c, int maxElements);
}
  • ArrayBlockingQueue
  • LinkedBlockingQueue
  • PriorityBlockingQueue
  • SynchronousQueue
7、FutureTask
public interface Future<V> {
   
 // 取消任务
  boolean cancel(boolean mayInterruptIfRunning);
 // 是否已取消
  boolean isCancelled();
 // 是否完成
  boolean isDone();
 // 获取结果
  V get() throws InterruptedException, ExecutionException;
 // 超时获取结果
  V get(long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException;
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
   
  void run();
}
public class FutureTask<V> implements RunnableFuture<V> {
   
}
8、源码解读
1.源码分析
  • 向ThreadPool提交任务 - execute()
  • 创建新线程 - addWorker(Runnable firstTask, boolean core)
  • 线程的主循环 - Worker.runWorker(Worker w)
  • 从队列中获取排队的任务 - getTask()
  • 线程结束 - processWorkExit(Worker w, boolean completedAbruptyly)
  • shutdown()、shutdownNow()、tryTerminated()
计数通用逻辑:先+1,再处理,若处理失败再-1
2.变量
// ctl = 线程数量 + 线程池状态(高3位表示线程池状态,低29位表示线程池线程数量)
// 默认值 0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 29 位
private static final int COUNT_BITS = Integer.SIZE - 3;
// 向左移动29位,30位为1,其余为0,减1,则为 29个1
private static final int CAPACITY  = (1 << COUNT_BITS) - 1;
// 线程池运行状态
// ctl < 0 时代表运行状态
private static final int RUNNING  = -1 << COUNT_BITS; // 111 
private static final int SHUTDOWN  = 0 << COUNT_BITS; // 000 
private static final int STOP    = 1 << COUNT_BITS; // 001
private static final int TIDYING  = 2 << COUNT_BITS; // 010 过度状态
private static final int TERMINATED = 3 << COUNT_BITS; // 011
// 获取当前线程池运行状态 ~CAPACITY = 1110 0000 0000... :前面3个1,后面29个0
private static int runStateOf(int c)   {
    return c & ~CAPACITY; }
// 获取当前线程池的线程数量 CAPACITY = 0001 1111 1111... :前面3个0,后面29个1
private static int workerCountOf(int c) {
    return c & CAPACITY; }
// 获取 ctl 的值
private static int ctlOf(int rs, int wc) {
    return rs | wc; }
// 任务队列,存放任务
private final BlockingQueue<Runnable> workQueue;
// Worker -> Runnable workers 存放任务线程的集合
private final HashSet<Worker> workers = new HashSet<Worker>();
3.线程池状态

ThreadPool 线程池的5种状态:

  • RUNNING :接收新任务和进程队列任务
  • SHUTDOWN :不接收新任务,但是接收进程队列任务
  • STOP :不接收新任务也不接收进程队列任务,并且中断正在执行中的任务
  • TIDYING :所有任务终止,线程数量为0,线程池转为 TIDING,将会执行 terminated 钩子方法
  • TERMINATED: terminated()执行完成
RUNNING: Accept new tasks and process queued tasks
SHUTDOWN: Don't accept new tasks, but process queued tasks
STOP:   Don't accept new tasks, don't process queued tasks
   and interrupt in-progress tasks
TIDYING: All tasks have terminated, workerCount is zero,
   the thread transitioning to state TIDYING
   will run the terminated() hook method
TERMINATED: terminated() has completed

状态之间的转换:

  • RUNNING -> SHUTDOWN:调用 shutdown() 方法
  • (RUNNING/SHUTDOWN) -> STOP :调用shutdownNow()方法
  • SHUTDOWN -> TIDING :队列和线程池都是空的
  • STOP -> TIDING :线程池为空
  • TIDING -> TERMINATED :钩子函数 terminated()执行完成
4.构造器
// 构造器开始
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;
}
5.execute(…)
public void execute(Runnable command) {
   
    // 基本判空
    if (command == null)
        throw new NullPointerException();
    // 获取 ctl 值:线程池状态及线程数 
    int c = ctl.get();
    // ① 线程池线程数量小于核心线程数,添加核心线程
    if (workerCountOf(c) < corePoolSize) {
   
        // 提交任务,true表示核心线程,添加成功直接返回
        if (addWorker(command, true))
            return
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值