深入系统底层剖析为什么需要线程池

线程池Exceutor框架解析

线程池实现原理剖析

线程池执行流程源码解读

如何合理配置线程池的大小

  1. public ThreadPoolExecutor(int corePoolSize,
  2. int maximumPoolSize,
  3. long keepAliveTime,
  4. TimeUnit unit,
  5. BlockingQueue<Runnable> workQueue,
  6. ThreadFactory threadFactory) {
  7. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
  8. threadFactory, defaultHandler);
  9. }
  • corePoolSize:线程池保有的最小线程数。
  • maximumPoolSize:线程池创建的最大线程数。
  • keepAliveTime:上面提到项目根据忙闲来增减人员,那在编程世界里,如何定义忙和闲呢?很简单,一个线程如果在一段时间内,都没有执行任务,说明很闲,keepAliveTime 和 unit 就是用来定义这个“一段时间”的参数。也就是说,如果一个线程空闲了keepAliveTime & unit这么久,而且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了。
  • unit:keepAliveTime 的时间单位
  • workQueue:任务队列
  • threadFactory:线程工厂对象,可以自定义如何创建线程,如给线程指定name。
  • handler:自定义任务的拒绝策略。线程池中所有线程都在忙碌,且任务队列已满,线程池就会拒绝接收再提交的任务。handler 就是拒绝策略,包括 4 种(即RejectedExecutionHandler 接口的 4个实现类)。
    a. AbortPolicy:默认的拒绝策略,直接抛出异常,throws RejectedExecutionException
    b. CallerRunsPolicy:关闭当前业务,如果被丢弃的线程任务为关闭,则执行改下次的任务。提交任务的线程自己去执行该任务
    c. DiscardPolicy:直接丢弃任务,不抛出任何异常
    d. DiscardOldestPolicy:丢弃最老的任务,加入新的任务
    e. 自定义拒绝策略。
  1. ThreadPoolExecutor THREAD_POOL_EXECUTOR =
  2. new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2,
  3. Runtime.getRuntime().availableProcessors() * 2,
  4. 0L, TimeUnit.MILLISECONDS,
  5. new LinkedBlockingQueue<Runnable>(200),
  6. new ThreadFactoryBuilder().setNameFormat("EXPORT-EXCEL_THREAD-POOL-%d").build());
  7. corePoolSize: Runtime.getRuntime().availableProcessors() * 2 (获取核心CPU数*2)
  8. maximumPoolSizeRuntime.getRuntime().availableProcessors() * 2 (获取核心CPU数*2)
  9. keepAliveTime0
  10. workQueueLinkedBlockingQueue(200)
  11. LinkedBlockingQueue\不指定容量,默认为Integer.MAX_VALUE,也就是无界队列。所以为了避免队列过大造成机器负载或者内存爆满的情况出现,我们在使用的时候建议手动传一个队列的大小。
  12. threadFactory: ThreadFactoryBuilder().setNameFormat("EXPORT-EXCEL_THREAD-POOL-%d").build()
  • 线程池是什么时候创建线程的?
    • 任务提交的时候

_

  • 任务runnable task是先放到core到maxThread之间的线程,还是先放到队列?
    • 先放队列!!!

_

  • 队列中的任务是什么时候取出来的?

    • worker中 runWorker() 一个任务完成后,会取下一个任务
  • 什么时候会触发reject策略?

    • 队列满并且maxthread也满了, 还有新任务,默认策略是reject
  • core到maxThread之间的线程什么时候会die?

    • 没有任务时,或者抛异常时。
    • core线程也会die的,core到maxThread之间的线程有可能会晋升到core线程区间,
    • core max只是个计数,线程并不是创建后就固定在一个区间了
  • task抛出异常,线程池中这个work thread还能运行其他任务吗?

    • 不能。 但是会创建新的线程, 新线程可以运行其他task。
    • 对于 schedulerThreadPoolExecutor? 虽然有新线程,但是旧的循环任务不会再继续执行了, 开发实践推荐任务中捕获所有Exception