当前位置: 首页 > news >正文

Java线程池那点事(面试高频)

1. 线程的生命周期

NEW -> RUNNABLE -> BLOCKED -> WAITING -> TIMED_WAIT -> TERMINATED

2. 线程池参数

  • int corePoolSize -- 核心线程数
  • int maximumPoolSize -- 最大线程数
  • long keepAliveTime -- 非核心线程探活时间
  • TimeUnit unit -- 非核心线程探活时间单位
  • BlockingQueue<Runnable> workQueue -- 阻塞队列
  • RejectedExecutionHandler handler -- 拒绝策略

    3. 线程池的工作原理

    • 任务到达时先判断是否有空闲线程,如果有则使用空闲线程。
    • 如果没有空闲线程,则判断线程数是否大于核心线程数,如果小于核心线程数则创建新的线程。
    • 如果大于核心线程数,则将任务加入到阻塞队列。
    • 当阻塞队列满时,则创建非核心线程,如果线程数大于等于最大线程数,则走拒绝策略。
    • 当一定时间没有任务后,非核心线程就会自动销毁。

    4. 如何手动启动核心线程

    • prestartAllCoreThreads():启动所有核心线程并返回启动的线程数。
    • prestartCoreThread():启动一个线程,等待任务。如果已达到核心线程数,这个方法返回 false,否则返回 true。

    5. 线程池拒绝策略

    • 丢弃任务,抛异常(默认)。
    • 丢弃任务,不抛异常。
    • 丢弃队列前面的任务(最旧的任务),从新提交被拒绝的任务。
    • 由调用线程来执行。

    6. 创建线程池需要注意哪些点

    • 设置合理的核心线程数以及最大线程数,避免OOM。
    • 设置阻塞队列的长度,避免OOM。
    • 自定义线程工厂,为创建的线程设置名称。
    • 设置合理的线程活跃时间以及时间单位,有利于非核心线程的回收。
    • 选择合适的拒绝策略,默认抛出RejectedExecutionexception类型的Runtimeeexception。(队列满了,线程数已经达到了最大线程数)。
    • 核心线程数建议设置为CPU核数,最大线程数建议设置为CPU核数*2(需要根据是否IO操作密集来决定)。

    7. 如何给线程池创建的线程设置名称

    // 创建自定义的ThreadFactory
    ThreadFactory customThreadFactory = newCustomThreadFactory("MyThreadPool");// 使用自定义的ThreadFactory创建线程池
    ExecutorService executor = newThreadPoolExecutor( 2, 4, 10, TimeUnit.SECONDS, newArrayBlockingQueue<>(2), customThreadFactory);

    8. 线程池如何知道线程任务是否执行完

    • 通过 isTerminated() 判断线程池内是否还有线程在运行。
    • 通过 submit() 方法提供的 Feture 返回值的 get()。
    • 通过 CountDownLatch 计数器,设置计数值为 1,在代码块后面用 await() 阻塞,当计数值为 0 时,await() 会放行。
    • 使用 shutdown() 和 awaitTermination()。shutdown() 关闭线程池不在接受新任务,awaitTermination() 等待所有任务执行完成。
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;public class ThreadPoolExample {public static void main(String[] args) throws InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(10);// 提交一些任务for (int i = 0; i < 10; i++) {executorService.submit(() -> {// 模拟任务处理System.out.println("任务开始处理:" + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("任务处理完成:" + Thread.currentThread().getName());});}// 关闭线程池,不再接受新任务executorService.shutdown();// 等待所有任务完成if (executorService.awaitTermination(60, TimeUnit.SECONDS)) {System.out.println("所有任务都已处理完成");} else {System.out.println("有任务未能在指定时间内完成");}}
    }
    

    9. Executors线程池

    • Executors.newCachedThreadPool(),缓存池。核心线程:0,最大线程:int.max,活跃时间:60s,队列:同步队列(SynchronousQueue,放入一个元素时,必须有一个线程准备好接收该元素,否则插入操作将阻塞,直到有线程来接收)。
    • Executors.newFixedThreadPool(10),固定大小线程池。核心线程:10,最大线程:10,活跃时间:0s,队列:阻塞队列。
    • Executors.newScheduledThreadPool(5),任务调度池。核心线程:5,最大线程:int.max,活跃时间:10ms,队列:延迟队列(DelayedWorkQueue)。
    • Executors.newSingleThreadExecutor(),单线程池。核心线程:1,最大线程:1,活跃时间:0s,队列:阻塞队列。
    • Executors.newWorkStealingPool(),工作窃取线程池,通过ForkJoinPool实现的。

    10. 如何合理使用线程池

    10.1 使用自定义线程池

    new ThreadPoolExecutor(coreThreads, poolSize, 10, TimeUnit.SECONDS,  state.threadPoolQueue, new ThreadPoolExecutor.AbortPolicy());

    10.2 核心线程数、最大线程数、阻塞队列大小设置

    10.2.1 CPU密集型

    • 核心线程数:CPU核数 + 1。
    • 最大线程数:核心线程数的 2 - 3 倍。
    • 队列大小:需要考虑任务的到达速率(任务产生的频率)、任务的执行时间和系统资源。如果系统资源有限或者任务不能长时间等待,可以设置较小的队列。反之任务到达速率较快,可以长时间执行,且系统资源充足,可以设置较大的队列。旺店通任务队列大小100,阻塞队列使用的是ArrayBlockingQueue。

    10.2.2 IO密集型

    • 核心线程数:CPU核数 * 2。
    • 最大线程数:核心线程数的 2 - 3 倍。
    • 队列大小:需要考虑任务的到达速率(任务产生的频率)、任务的执行时间和系统资源。如果系统资源有限或者任务不能长时间等待,可以设置较小的队列。反之任务到达速率较快,可以长时间执行,且系统资源充足,可以设置较大的队列。旺店通任务队列大小100,阻塞队列使用的是ArrayBlockingQueue。
    http://www.xdnf.cn/news/129205.html

    相关文章:

  1. ASR VAD TTS
  2. VLA 论文精读(十八)π0.5: a Vision-Language-Action Model with Open-World Generalization
  3. JavaFX 第三篇 HostServices和Platform
  4. 交通运输行业综合智慧监管平台:商贸物流的安全与效率引擎
  5. Windows下QT打包后程序运行后弹出CMD命令窗口的问题解决方法
  6. vxe-table封装表头
  7. MSHFlexGrid 控件网格赋值指南方案
  8. Python爬虫实战:移动端逆向工具Fiddler经典案例
  9. 24FIC 决赛 计算机部分
  10. 【HFP】蓝牙语音通话控制深度解析:来电拒接与通话终止协议
  11. 【前端】【业务场景】【面试】在前端开发中,如何优化 SVG(可缩放矢量图形)的性能,特别是在处理复杂图形和动画时
  12. MCP实战-本地MCP Server+Cursor实践
  13. AI日报 - 2025年04月25日
  14. C语言-函数-1
  15. 入门-C编程基础部分:19、输入 输出
  16. 位带和位带别名区
  17. python自动化学习六:断言
  18. 【Linux系统篇】:什么是信号以及信号是如何产生的---从基础到应用的全面解析
  19. redis相关问题整理
  20. 2024年ASOC SCI1区TOP:改进灰狼算法IGWO+股票指数收益预测,深度解析+性能实测
  21. 传感器测量(图片流程)
  22. ECharts学习之 toolbox 工具栏
  23. 大模型数据预处理方法总结
  24. 旋转磁体产生的场-对导航姿态的影响
  25. 数据库--回表
  26. Spring Security基础入门
  27. 电子处方模块开发避坑指南:从互联网医院系统源码实践出发
  28. vuex持久化vuex-persistedstate,存储的数据刷新页面后导致数据丢失
  29. 【解决】Android Gradle Sync 报错 Could not read workspace metadata
  30. 【C/C++】深入理解指针(四)