2024年4月20日发(作者:)
线程池的工作流程面试题
面试题1:ThreadPoolExecutor有哪些常用的方法?
ThreadPoolExecutor有如下常用方法:
submit()/execute():执行线程池shutdown()/shutdownNow():终止线程池
isShutdown():判断线程是否终止getActiveCount():正在运行的线程数
getCorePoolSize():获取核心线程数getMaximumPoolSize():获取最大线程数
getQueue():获取线程池中的任务队列allowCoreThreadTimeOut(boolean):设置
空闲时是否回收核心线程这些方法可以用来终止线程池、线程池监控等。
面试题2:说说submit(和 execute两个方法有什么区别?
submit()和 execute()都是用来执行线程池的,只不过使用 execute()执行线程
池不能有返回方法,而使用 submit()可以使用 Future接收线程池执行的返回值。
面试题3:shutdownNow()和 shutdown()两个方法有什么区别?
shutdownNow()和 shutdown()都是用来终止线程池的,它们的区别是,使用
shutdown()程序不会报错,也不会立即终止线程,它会等待线程池中的缓存任务
执行完之后再退出,执行了 shutdown()之后就不能给线程池添加新任务了;
shutdownNow()会试图立马停止任务,如果线程池中还有缓存任务正在执行,则
会抛出 ruptedException: sleep interrupted异常。
面试题4:了解过线程池的工作原理吗?
当线程池中有任务需要执行时,线程池会判断如果线程数量没有超过核心数
量就会新建线程池进行任务执行,如果线程池中的线程数量已经超过核心线程数,
这时候任务就会被放入任务队列中排队等待执行;如果任务队列超过最大队列数,
并且线程池没有达到最大线程数,就会新建线程来执行任务;如果超过了最大线
程数,就会执行拒绝执行策略。
面试题5:线程池中核心线程数量大小怎么设置?
「CPU密集型任务」:比如像加解密,压缩、计算等一系列需要大量耗费 CPU
资源的任务,大部分场景下都是纯 CPU计算。尽量使用较小的线程池,一般为
CPU核心数+1。因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,
会造成CPU过度切换。
「IO密集型任务」:比如像 MySQL数据库、文件的读写、网络通信等任务,
这类任务不会特别消耗 CPU资源,但是 IO操作比较耗时,会占用比较多时间。
可以使用稍大的线程池,一般为2*CPU核心数。IO密集型任务CPU使用率并不
高,因此可以让CPU在等待IO的时候有其他线程去处理别的任务,充分利用CPU
时间。
另外:线程的平均工作时间所占比例越高,就需要越少的线程;线程的平均
等待时间所占比例越高,就需要越多的线程;
以上只是理论值,实际项目中建议在本地或者测试环境进行多次调优,找到
相对理想的值大小。
面试题6:线程池为什么需要使用(阻塞)队列?
主要有三点:
因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且
会造成cpu过度切换。创建线程池的消耗较高。面试题7:线程池为什么要使用阻
塞队列而不使用非阻塞队列?
阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进
入wait状态,释放cpu资源。
当队列中有任务时才唤醒对应线程从队列中取出消息进行执行。
使得在线程不至于一直占用cpu资源。
(线程执行完任务后通过循环再次从任务队列中取出任务进行执行,代码片
段如下
while (task != null | (task = getTask()) != null) {})。
不用阻塞队列也是可以的,不过实现起来比较麻烦而已,有好用的为啥不用
呢?
面试题8:了解线程池状态吗?
通过获取线程池状态,可以判断线程池是否是运行状态、可否添加新的任务
以及优雅地关闭线程池等。
RUNNING:线程池的初始化状态,可以添加待执行的任务。SHUTDOWN:线
程池处于待关闭状态,不接收新任务仅处理已经接收的任务。STOP:线程池立即
关闭,不接收新的任务,放弃缓存队列中的任务并且中断正在处理的任务。
TIDYING:线程池自主整理状态,调用 terminated()方法进行线程池整理。
发布者:admin,转转请注明出处:http://www.yc00.com/web/1713585550a2278281.html
评论列表(0条)