欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > Java 线程池基础知识

Java 线程池基础知识

2025/6/21 12:51:29 来源:https://blog.csdn.net/m0_37242314/article/details/148797663  浏览:    关键词:Java 线程池基础知识

一、线程池的主要核心参数:

  1. CORE_POOL_SIZE:

    • 核心线程数,设置为JVM可用的处理器核心数

    • 这些线程会一直存活,即使处于空闲状态

  2. MAX_POOL_SIZE:

    • 最大线程数

    • 当队列满且核心线程都在忙时,会创建新线程直到达到此上限

  3. QUEUE_CAPACITY:

    • 工作队列的容量

    • 在核心线程都忙时,新任务会先进入队列而不是创建新线程

  4. KEEP_ALIVE_TIME:

    • 非核心线程的空闲存活时间,设置为1秒

    • 超过核心线程数的线程在空闲超过此时间后会被终止

  5. TimeUnit:

    • 存活时间的单位

  6. workQueue

    • 使用有界队列来存储等待执行的任务

  7. RejectedExecutionHandler:

    • CallerRunsPolicy 默认策略,直接抛出异常

    • DiscardPolicy 静默丢弃,不抛异常

    • DiscardOldestPolicy  丢弃队列最旧任务,再尝试提交新任务

    • CallerRunsPolicy 调用者线程自己执行任务

    • 自定义拒绝策略

      • 如果内置策略不满足需求,可以实现 RejectedExecutionHandler 接口自定义策略:

        ExecutorService executor = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,TimeUnit.SECONDS,new LinkedBlockingQueue<>(capacity),(Runnable r, ThreadPoolExecutor executor) -> {// 自定义逻辑,如记录日志、降级处理等System.err.println("Task rejected: " + r);}
        );

二、四种常用的线程池

但是Java 通过 Executors 类提供了四种常用的线程池实现,每种都有其特定的使用场景和优缺点。

1. FixedThreadPool(固定大小线程池)

创建方式

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}

优点

  • 线程数量固定,可以控制最大并发数

  • 适用于负载较重的服务器环境

  • 线程不会被回收,减少了线程创建销毁的开销

  • 任务队列无界,可以接收大量任务

缺点

  • 使用无界队列(LinkedBlockingQueue),可能导致内存溢出

  • 如果线程因异常终止,会创建新线程替代

  • 不适合任务执行时间差异很大的场景

适用场景

  • 需要限制线程数量的场景

  • CPU密集型任务

2. CachedThreadPool(可缓存线程池)

创建方式

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}

优点

  • 线程数量几乎无限制(Integer.MAX_VALUE)

  • 空闲线程会被回收(默认60秒)

  • 自动扩展线程池大小应对突发流量

  • 使用SynchronousQueue,任务不会被排队,它是一个零容量队列(一个不存储元素的阻塞队列)。

缺点

  • 线程数量无限制可能导致系统资源耗尽

  • 不适合处理执行时间较长的任务

  • 大量短任务可能导致频繁创建销毁线程

适用场景

  • 大量短生命周期的异步任务

  • 负载较轻的服务器

  • IO密集型任务

3. SingleThreadExecutor(单线程线程池)

创建方式

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}

优点

  • 保证所有任务按提交顺序执行

  • 不需要处理线程同步问题

  • 线程异常终止后会创建新线程继续执行

缺点

  • 性能低下,无法利用多核CPU

  • 使用无界队列,可能内存溢出

  • 一个任务阻塞会影响后续所有任务

适用场景

  • 需要任务顺序执行的场景

  • 不需要并发性的任务

  • 日志处理等顺序性要求高的任务

4. ScheduledThreadPool(定时任务线程池)

创建方式

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(corePoolSize);public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);}public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}

优点

  • 支持定时及周期性任务执行

  • 可以替代Timer类,功能更强大

  • 线程数固定,不会无限增长

  • 异常处理比Timer更可靠

缺点

  • 复杂定时任务逻辑实现较复杂

  • 执行时间较长的任务可能影响后续任务

  • 使用DelayedWorkQueue,任务过多可能内存溢出

适用场景

  • 需要定时执行的任务

  • 周期性任务(如心跳检测)

  • 需要延迟执行的任务

总结对比

线程池类型核心线程数最大线程数工作队列线程存活时间适用场景
FixedThreadPool固定固定LinkedBlockingQueueCPU密集型
CachedThreadPool0Integer.MAX_VALUESynchronousQueue60秒短生命期IO密集型
SingleThreadExecutor11LinkedBlockingQueue顺序执行任务
ScheduledThreadPool固定Integer.MAX_VALUEDelayedWorkQueue定时/周期性任务

通用缺点

  1. 除CachedThreadPool外,其他三种都使用无界队列,可能导致OOM

  2. 默认的线程工厂创建的线程没有有意义的名称,不利于问题排查

  3. 默认的拒绝策略可能不符合业务需求

最佳实践

  • 对于生产环境,建议根据业务需求自定义ThreadPoolExecutor

  • 为线程设置合理的名称前缀

  • 根据任务类型选择合适的队列和拒绝策略

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词