自己动手写线程池——向JDK线程池进发

自己动手写线程池——向JDK线程池进发前言在前面的文章自己动手写乞丐版线程池中,我们写了一个非常简单的线程池实现,这个只是一个非常简单的实现,在本篇文章当中我们将要实现一个和JDK内部实现的线程池非常相似的线程池 。
JDK线程池一瞥我们首先看一个JDK给我们提供的线程池ThreadPoolExecutor的构造函数的参数:
public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              ThreadFactory threadFactory,                              RejectedExecutionHandler handler)参数解释:

  • corePoolSize:这个参数你可以理解为线程池当中至少需要 corePoolSize 个线程,初始时线程池当中线程的个数为0 , 当线程池当中线程的个数小于 corePoolSize 每次提交一个任务都会创建一个线程 , 并且先执行这个提交的任务,然后再去任务队列里面去获取新的任务,然后再执行 。
  • maximumPoolSize:这个参数指的是线程池当中能够允许的最大的线程的数目 , 当任务队列满了之后如果这个时候有新的任务想要加入队列当中,当发现队列满了之后就创建新的线程去执行任务,但是需要满足最大的线程的个数不能够超过 maximumPoolSize。
  • keepAliveTime 和 unit:这个主要是用于时间的表示 , 当队列当中多长时间没有数据的时候线程自己退出,前面谈到了线程池当中任务过多的时候会超过 corePoolSize,当线程池闲下来的时候这些多余的线程就可以退出了 。
  • workQueue:这个就是用于保存任务的阻塞队列 。
  • threadFactory:这个参数倒不是很重要,线程工厂 。
  • handler:这个表示拒绝策略 , JDK给我们提供了四种策略:
    • AbortPolicy:抛出异常 。
    • DiscardPolicy:放弃这个任务 。
    • CallerRunPolicy:提交任务的线程执行 。
    • DiscardOldestPolicy:放弃等待时间最长的任务 。
如果上面的参数你不能够理解 , 可以先阅读这篇文章自己动手写乞丐版线程池 。基于上面谈到的参数,线程池当中提交任务的流程大致如下图所示:
自己动手写线程池——向JDK线程池进发

文章插图
自己动手实现线程池根据前面的参数分析我们自己实现的线程池需要实现一下功能:
  • 能够提交Runnable的任务和Callable的任务 。
  • 线程池能够自己实现动态的扩容和所容,动态调整线程池当中线程的数目,当任务多的时候能够增加线程的数目,当任务少的时候多出来的线程能够自动退出 。
  • 有自己的拒绝策略 , 当任务队列满了 , 线程数也达到最大的时候,需要拒绝提交的任务 。
线程池参数介绍  private AtomicInteger ct = new AtomicInteger(0); // 当前在执行任务的线程个数  private int corePoolSize;  private int maximumPoolSize;  private long keepAliveTime;  private TimeUnit unit;  private BlockingQueue<Runnable> taskQueue;  private RejectPolicy policy;  private ArrayList<Worker> workers = new ArrayList<>();  private volatile boolean isStopped;  private boolean useTimed;参数解释如下: