Java线程池笔记

简介: 总结一下Java线程池相关八股文

Java相关文章


线程池参数

  1. corePoolSize 线程池核心线程数
  1. 线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。
  1. maximumPoolSize 线程池最大线程数量
  1. 一个任务被提交到线程池以后,首先会找有没有空闲存活线程,如果有则直接将任务交给这个空闲线程来执行,如果没有则会缓存到工作队列(后面会介绍)中,如果工作队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。
  1. keepAliveTime 空闲线程存活时间
  1. 一个非核心线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定
  1. unit 空闲线程存活时间单位
  1. keepAliveTime的计量单位
  1. workQueue 工作队列
  1. ArrayBlockingQueue
  1. 数组有界大小固定
  2. 基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
  1. LinkedBlockingQuene
  1. 链表有界大小可变
  2. 基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。
  1. SynchronousQuene
  1. SynchronousQueue的capacity是0,该队列不存储任何元素
  2. 也就是说SynchronousQueue的每一次insert操作,必须阻塞到其他线程的remove操作。而每一个remove操作也必须阻塞其他线程的insert操作。
  1. PriorityBlockingQueue
  1. 具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
  1. 队列管理任务方法

抛出异常

特殊值

阻塞

超时

插入

add(e)

offer(e)

put(e)

offer(e, time, unit)

移除

remove()

poll()

take()

poll(time, unit)

检查

element()

peek()

不可用

不可用



handler 拒绝策略

  1. CallerRunsPolicy
  1. 该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
  1. AbortPolicy
  1. 该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。
  1. DiscardPolicy
  1. 该策略下,直接丢弃任务,什么都不做。
  1. DiscardOldestPolicy
  1. 该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列


线程池核心线程数为0任务怎么创建

  1. 当核心线程数为0的时候,会创建一个非核心线程进行执行
  2. 核心线程数不为0的时候,如果核心线程数在执行,会有一个非核心线程数从队列中取对象执行线程
  3. 核心线程数执行的是队列的take,非核心线程数执行队列的offer和poll
  4. 核心线程数不为0且队列为SynchronousQueue时,就成了单线程运行了


线程池一个任务从被提交到被执行,线程池做了哪些工作?

  1. 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行他们。
  2. 当调用execute()方法添加一个任务时,线程池会做如下判断:
  1. 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务
  2. 如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列
  3. 如果这时候队列满了,而且正在运行的线程数量小于maximunPoolSize,那么还是要创建非核心线程立刻运行这个任务
  4. 如果队列满了,而且正在运行的线程数量大于或等于maximunPoolSize,那么线程池会抛出RejectedExecutionException
  1. 当一个线程完成任务时,它会从队列中取下一个任务来执行
  2. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小



常见线程池有哪些

  1. newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
  4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
相关文章
|
9天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
24天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
本系列教程笔记详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。若需快速学习Kotlin,建议查看“简洁”系列教程。本期重点介绍了Kotlin与Java的共存方式,包括属性、单例对象、默认参数方法、包方法、扩展方法以及内部类和成员的互操作性。通过这些内容,帮助你在项目中更好地结合使用这两种语言。
41 1
|
25天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
32 2
|
21天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
100 38
|
15天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
15天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
15天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
21天前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
58 4
|
21天前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
89 2
|
23天前
|
缓存 监控 Java
java中线程池的使用
java中线程池的使用