面试官:创建线程池的几种方式以及区别

创建线程池有多种方式,主要通过 Java 的 java.util.concurrent 包提供的 Executors 类来实现。
首页 新闻资讯 行业资讯 面试官:创建线程池的几种方式以及区别

创建线程池有多种方式,主要通过 Java 的 java.util.concurrent 包提供的 Executors 工具类来实现。以下是几种常见的线程池类型及其区别:


1. FixedThreadPool

//创建一个固定大小的线程池,模拟提交 10 个任务到线程池。importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclass FixedThreadPoolExample {publicstatic void main(String[]args){
        ExecutorService fixedThreadPool=Executors.newFixedThreadPool(3);// 创建一个具有3个线程的固定线程池for(inti=1;i<=10;i++){
            finalinttask=i;fixedThreadPool.execute(()->{
                System.out.println("执行任务 "+task+",线程:"+Thread.currentThread().getName());});}
        
        fixedThreadPool.shutdown();}
}
  • 特点:创建一个固定大小的线程池,池中始终保持指定数量的线程。

  • 适用场景:适用于固定并发数的任务,比如定量的短期并发任务。

  • 优点:能够有效地控制线程数量,避免资源消耗过多。

  • 缺点:如果所有线程都在执行任务,而新的任务不断提交,可能会造成等待队列过长。

2. CachedThreadPool

//创建一个缓存线程池来处理任务,模拟并发执行 10 个任务importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclass CachedThreadPoolExample {publicstatic void main(String[]args){
        ExecutorService cachedThreadPool=Executors.newCachedThreadPool();for(inti=1;i<=10;i++){
            finalinttask=i;cachedThreadPool.execute(()->{
                System.out.println("执行任务 "+task+",线程:"+Thread.currentThread().getName());});}
        
        cachedThreadPool.shutdown();}
}
  • 特点:创建一个可以根据需要自动扩展的线程池,当线程空闲 60 秒后会被回收。

  • 适用场景:适合执行大量耗时较短的异步任务。

  • 优点:线程数量不受限制(受系统资源限制),对于任务短小、并发量大但不稳定的场景效果较好。

  • 缺点:如果任务增长过快,会创建大量线程,可能会造成 OOM(Out of Memory)异常。


3. SingleThreadExecutor

//创建一个单线程线程池,顺序执行多个任务。importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclass SingleThreadExecutorExample {publicstatic void main(String[]args){
        ExecutorService singleThreadExecutor=Executors.newSingleThreadExecutor();for(inti=1;i<=5;i++){
            finalinttask=i;singleThreadExecutor.execute(()->{
                System.out.println("执行任务 "+task+",线程:"+Thread.currentThread().getName());});}
        
        singleThreadExecutor.shutdown();}
}
  • 特点:创建单线程化的线程池,始终只有一个工作线程。

  • 适用场景:适用于需要保证任务顺序执行的场景,避免多线程并发的复杂性。

  • 优点:可以保证任务按顺序执行,适合单一任务队列。

  • 缺点:性能较低,不适合需要高并发的场景。


4. ScheduledThreadPool

//创建一个支持定时和周期性执行任务的线程池,示例任务每隔 2 秒执行一次,共执行 3 次。importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurrent.TimeUnit;publicclass ScheduledThreadPoolExample {publicstatic void main(String[]args){
        ScheduledExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(2);// 创建一个有2个线程的定时线程池scheduledThreadPool.scheduleAtFixedRate(()->{
            System.out.println("定时任务执行,线程:"+Thread.currentThread().getName());},0,2,TimeUnit.SECONDS);// 0秒延迟后开始,每隔2秒执行一次任务// 程序运行5秒后关闭线程池try {
            Thread.sleep(5000);} catch(InterruptedException e){
            e.printStackTrace();}
        
        scheduledThreadPool.shutdown();}
}
  • 特点:创建一个支持定时或周期性任务执行的线程池。

  • 适用场景:适合执行定时任务或周期性任务,比如定时器、定时检查等。

  • 优点:可以方便地实现周期性任务管理。

  • 缺点:对高并发任务的处理能力较弱,通常用于任务量不大的场景。


5. WorkStealingPool(Java 8 引入)

//创建一个基于任务分解的线程池来并行执行多个任务,适合处理需要拆分的小任务。importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.TimeUnit;publicclass WorkStealingPoolExample {publicstatic void main(String[]args)throws InterruptedException {
        ExecutorService workStealingPool=Executors.newWorkStealingPool();// 创建默认线程数为CPU核心数的工作窃取线程池for(inti=1;i<=8;i++){
            finalinttask=i;workStealingPool.submit(()->{
                System.out.println("执行任务 "+task+",线程:"+Thread.currentThread().getName());try {
                    TimeUnit.SECONDS.sleep(1);} catch(InterruptedException e){
                    e.printStackTrace();}
            });}// 让主线程等待子任务执行完成workStealingPool.awaitTermination(3,TimeUnit.SECONDS);workStealingPool.shutdown();}
}
  • 特点:基于 ForkJoinPool 实现,适用于大任务拆分成小任务的并行处理。线程数默认为处理器核心数。

  • 适用场景:适合处理较为复杂的并行任务,比如分治算法。

  • 优点:通过“工作窃取”算法实现任务的动态负载均衡,能够有效提升多核 CPU 的利用率。

  • 缺点:由于线程数不固定,可能对资源使用较多,不适合所有应用。


区别总结

线程池类型

线程数量控制

特点

适用场景

FixedThreadPool

固定数量

固定线程数,适合稳定的任务并发

固定并发任务

CachedThreadPool

自动扩展

动态扩展,空闲线程自动回收,适合任务短小但并发量不稳定

短期的异步并发任务

SingleThreadExecutor

单一线程

单线程顺序执行任务,保证顺序

顺序执行的任务

ScheduledThreadPool

可控核心线程数

支持定时或周期性任务

定时任务、周期性任务

WorkStealingPool

默认 CPU 核数

基于任务拆分并行处理,提高多核 CPU 利用率



26    2024-10-31 09:30:05    线程池 工具 Java