线程池面试题(不定期更新)

深度解读 Java线程池设计思想及源码实现

java 线程池有哪些关键属性?

corePoolSize,maximumPoolSize,workQueue,keepAliveTime,rejectedExecutionHandler

  • corePoolSize 到maximumPoolSize之间的线程会被回收,当然 corePoolSize的线程也可以通过设置而得到回收(allowCoreThreadTimeOut(true))。

  • workQueue 用于存放任务,添加任务的时候,如果当前线程数超过了corePoolSize,那么往该队列中插入任务,线程池中的线程会负责到队列中拉取任务。

  • keepAliveTime用于设置空闲时间,如果线程数超出了 corePoolSize,并且有些线程的空闲时间超过了这个值,会执行关闭这些线程的操作

  • rejectedExecutionHandler 用于处理当线程池不能执行此任务时的情况,默认有抛出 RejectedExecutionException 异常、忽略任务、使用提交任务的线程来执行此任务和将队列中等待最久的任务删除,然后提交此任务这四种策略,默认为抛出异常。

说说线程池中的线程创建时机?

注意:如果将队列设置为无界队列,那么线程数达到 corePoolSize 后,其实线程数就不会再增长了。因为后面的任务直接往队列塞就行了,此时 maximumPoolSize 参数就没有什么意义。

  • 如果当前线程数少于corePoolSize,那么提交任务的时候创建一个新的线程,并由这个线程执行这个任务;

  • 如果当前线程数已经达到corePoolSize,那么将提交的任务添加到队列中,等待线程池中的线程去队列中取任务;

  • 如果队列已满,那么创建新的线程来执行任务,需要保证池中的线程数不会超过maximumPoolSize,如果此时线程数超过了maximumPoolSize,那么执行拒绝策略。

任务执行过程中发生异常怎么处理?

  • 如果某个任务执行出现异常,那么执行任务的线程会被关闭,而不是继续接收其他任务。然后会启动一个新的线程来代替它。

什么时候会执行拒绝策略?

  • workers 的数量达到了 corePoolSize(任务此时需要进入任务队列),任务入队成功,与此同时线程池被关闭了,而且关闭线程池并没有将这个任务出队,那么执行拒绝策略。这里说的是非常边界的问题,入队和关闭线程池并发执行
  • workers 的数量大于等于corePoolSize,将任务加入到任务队列,可是队列满了,任务入队失败,那么准备开启新的线程,可是线程数已经达到 maximumPoolSize,那么执行拒绝策略。

四种ExecutorService线程池

线程池面试题(不定期更新)

  • newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
  • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

拒绝策略

  • ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
  • ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
  • ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)。
  • ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。

线程池

  • corePoolSize 为线程池的基本大小。
  • maximumPoolSize 为线程池最大线程大小。
  • keepAliveTimeunit则是线程空闲后的存活时间。
  • workQueue 用于存放任务的阻塞队列。
  • handler 当队列和最大线程池都满了之后的饱和策略

线程池面试题(不定期更新)

线程池面试题(不定期更新)

没那么简单的线程池