多线程面试题--线程池

目录

介绍

 线程池的核心参数/执行原理

核心参数

执行原理​编辑

常见的阻塞队列

ArrayBlockingQueue和LinkedBlockingQueue区别

如何确定核心线程数

线程池的种类有哪些

创建使用固定线程数的线程池

单线程化的线程池

可缓存线程池

 “延迟”和“周期执行”的线程池

 总结

 为什么不建议用Executors创建线程池


介绍

首先有一个问题,为什么要使用线程池呢?有两个原因,

第一个,每一次创建线程的时候都会占用一定的内存空间,如果无限的创建线程,可能会浪费内存,严重的情况可能会内存溢出。

第二个,cpu是有限的,同一时刻一个cpu只能处理一个线程,如果有大量的请求来了,我们创建了大量的线程,很多线程没有cpu的执行权,这些线程都得出去等待,会造成大量的线程之间的切换,也会造成性能变慢

所以一般来说都会使用线程池来管理线程,创建线程

多线程面试题--线程池_第1张图片

 线程池的核心参数/执行原理

核心参数

多线程面试题--线程池_第2张图片

corePoolSize 核心线程数目:线程池中主要执行任务的数量(不会释放)

maximumPoolSize 最大线程数目 = (核心线程+救急线程的最大数目):救急线程又叫临时线程

keepAliveTime 生存时间:救急线程的生存时间,生存时间内没有新任务(活跃任务),此线程资源会释放

unit 时间单位 - 救急线程的生存时间单位,如秒、毫秒等

workQueue 阻塞队列当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务

threadFactory 线程工厂 - 可以定制线程对象的创建,例如设置线程名字、是否是守护线程等

handler 拒绝策略 - 当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略

执行原理多线程面试题--线程池_第3张图片

常见的阻塞队列

workQueue - 当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务

1.ArrayBlockingQueue:基于数组结构的有界(有容量)阻塞队列,FIFO(先进先出)

2.LinkedBlockingQueue:基于单向链表结构的有界阻塞队列,FIFO

3.DelayedWorkQueue :是一个优先级队列,它可以保证每次出队的任务都是当前队列中执行时间最靠前的

4.SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移出操作。

ArrayBlockingQueue和LinkedBlockingQueue区别

多线程面试题--线程池_第4张图片

如何确定核心线程数

在解决这个问题前,我们需要知道两个东西,我们当前一个应用程序可以分为两种类型

n为cpu核数,cpu密集型任务,我们尽量减少线程之间的切换来增加效率,而IO密集型任务因为不太占cpu,所以它的核心数就会相对多一些

多线程面试题--线程池_第5张图片

 多线程面试题--线程池_第6张图片

 不同类型的程序对线程池的需求也不同。比如IO密集型的程序,由于线程会被IO操作所阻塞,因此可以设置比较多的线程数;而CPU密集型的程序,则需要控制线程的数量,避免CPU资源过度占用。

线程池的种类有哪些

java.util.concurrent.Executors类中提供了大量创建连接池的静态方法,常见就有四种

创建使用固定线程数的线程池

多线程面试题--线程池_第7张图片

单线程化的线程池

它只会用唯一的工作线程来执行任 务,保证所有任务按照指定顺序(FIFO)执行

多线程面试题--线程池_第8张图片

可缓存线程池

多线程面试题--线程池_第9张图片

 “延迟”和“周期执行”的线程池

多线程面试题--线程池_第10张图片

 多线程面试题--线程池_第11张图片

 总结

 多线程面试题--线程池_第12张图片

 为什么不建议用Executors创建线程池

多线程面试题--线程池_第13张图片

因此,为了更好地控制和管理线程池,推荐使用ThreadPoolExecutor类来手动创建线程池。通过使用ThreadPoolExecutor,可以根据具体的需求设置线程池的参数,例如核心线程数、最大线程数、队列类型等,以及自定义拒绝策略来处理任务无法执行的情况。

你可能感兴趣的:(java,开发语言)