线程池底层原理

线程池底层原理

ThreadPoolExecutor

参数

  1. corePoolSize(必填) : 核心线程数

  2. maximumPoolSize(必填):最大线程数

  3. keepAliveTime(必填):线程空闲时长。如果超过该时长,非核心线程就会被回收。

  4. unit(必填):指定keepAliveTime的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)

  5. workQueue(必填):任务队列。通过线程池的execute()方法提交的Runnable对象将存储在该队列中。

  6. threadFactory(可选):线程工厂。一般就用默认的。

  7. handler(可选):拒绝策略。当线程数达到最大线程数时就要执行饱和策略。

    拒绝策略可选值
    1、AbortPolicy(默认):放弃任务并抛出RejectedExecutionException异常。
    2、CallerRunsPolicy:由调用线程处理该任务。
    3、DiscardPolicy:放弃任务,但是不抛出异常。可以配合这种模式进行自定义的处理方式。
    4、DiscardOldestPolicy:放弃队列最早的未处理任务,然后重新尝试执行任务。

线程池运行机制

  1. 一个任务提交到线程池后,如果当前的线程数没达到核心线程数,则新建一个线程并且执行新任务,注意一点,这个新任务执行完后,该线程不会被销毁
  2. 如果达到了,则判断任务队列满了没,如果没满,则将任务放入任务队列;
  3. 如果满了,则判断当前线程数量是否达到最大线程数,如果没达到,则创建新线程来执行任务,注意,如果线程池中线程数量大于核心线程数,每当有线程超过了空闲时间,就会被销毁,直到线程数量不大于核心线程数;
  4. 如果达到了最大线程数,并且任务队列满了,就会执行饱和策略

总结公式:

存活任务数 <= 核心线程数时,线程池中工作线程数 = 存活任务数
核心线程数 + 队列容量 < 存活任务数 <= 最大线程数 + 队列容量时,工作线程数 = 存活任务数 - 队列容量

存放线程对象的容器为什么使用HashSet?

HashSet基于HashMap来实现的,基于hash函数和负载因子的设计可以减少hash碰撞的概率,这些操作的时间复杂度都是O(1)的,而且线程池里的线程对于顺序和优先级都没有要求,还可以自动去重。

posted @ 2021-12-19 18:06  Onvertex  阅读(117)  评论(0)    收藏  举报