目录
介绍
线程池的核心参数/执行原理
核心参数
执行原理编辑
常见的阻塞队列
ArrayBlockingQueue和LinkedBlockingQueue区别
如何确定核心线程数
线程池的种类有哪些
创建使用固定线程数的线程池
单线程化的线程池
可缓存线程池
“延迟”和“周期执行”的线程池
总结
为什么不建议用Executors创建线程池
介绍
首先有一个问题,为什么要使用线程池呢?有两个原因,
第一个,每一次创建线程的时候都会占用一定的内存空间,如果无限的创建线程,可能会浪费内存,严重的情况可能会内存溢出。
第二个,cpu是有限的,同一时刻一个cpu只能处理一个线程,如果有大量的请求来了,我们创建了大量的线程,很多线程没有cpu的执行权,这些线程都得出去等待,会造成大量的线程之间的切换,也会造成性能变慢
所以一般来说都会使用线程池来管理线程,创建线程
线程池的核心参数/执行原理
核心参数
corePoolSize 核心线程数目:线程池中主要执行任务的数量(不会释放)
maximumPoolSize 最大线程数目 = (核心线程+救急线程的最大数目):救急线程又叫临时线程
keepAliveTime 生存时间:救急线程的生存时间,生存时间内没有新任务(活跃任务),此线程资源会释放
unit 时间单位 - 救急线程的生存时间单位,如秒、毫秒等
workQueue 阻塞队列:当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务
threadFactory 线程工厂 - 可以定制线程对象的创建,例如设置线程名字、是否是守护线程等
handler 拒绝策略 - 当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略
执行原理
常见的阻塞队列
workQueue - 当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务
1.ArrayBlockingQueue:基于数组结构的有界(有容量)阻塞队列,FIFO(先进先出)。
2.LinkedBlockingQueue:基于单向链表结构的有界阻塞队列,FIFO。
3.DelayedWorkQueue :是一个优先级队列,它可以保证每次出队的任务都是当前队列中执行时间最靠前的
4.SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移出操作。
ArrayBlockingQueue和LinkedBlockingQueue区别
如何确定核心线程数
在解决这个问题前,我们需要知道两个东西,我们当前一个应用程序可以分为两种类型
n为cpu核数,cpu密集型任务,我们尽量减少线程之间的切换来增加效率,而IO密集型任务因为不太占cpu,所以它的核心数就会相对多一些
不同类型的程序对线程池的需求也不同。比如IO密集型的程序,由于线程会被IO操作所阻塞,因此可以设置比较多的线程数;而CPU密集型的程序,则需要控制线程的数量,避免CPU资源过度占用。
线程池的种类有哪些
在java.util.concurrent.Executors类中提供了大量创建连接池的静态方法,常见就有四种
创建使用固定线程数的线程池
单线程化的线程池
它只会用唯一的工作线程来执行任 务,保证所有任务按照指定顺序(FIFO)执行
可缓存线程池
“延迟”和“周期执行”的线程池
总结
为什么不建议用Executors创建线程池
因此,为了更好地控制和管理线程池,推荐使用ThreadPoolExecutor
类来手动创建线程池。通过使用ThreadPoolExecutor
,可以根据具体的需求设置线程池的参数,例如核心线程数、最大线程数、队列类型等,以及自定义拒绝策略来处理任务无法执行的情况。