【面试宝典】Java中创建线程池的几种方式以及区别

在这里插入图片描述

579a429daf314744b995f37351b46548

强烈推荐

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:人工智能

b004071ozy_05_amzn

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

1. FixedThreadPool

//创建一个固定大小的线程池,模拟提交 10 个任务到线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

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

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

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

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

2. CachedThreadPool

//创建一个缓存线程池来处理任务,模拟并发执行 10 个任务

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CachedThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        
        for (int i = 1; i <= 10; i++) {
            final int task = i;
            cachedThreadPool.execute(() -> {
                System.out.println("执行任务 " + task + ",线程:" + Thread.currentThread().getName());
            });
        }
        
        cachedThreadPool.shutdown();
    }
}
  • 特点:创建一个可以根据需要自动扩展的线程池,当线程空闲 60 秒后会被回收。
  • 适用场景:适合执行大量耗时较短的异步任务。
  • 优点:线程数量不受限制(受系统资源限制),对于任务短小、并发量大但不稳定的场景效果较好。
  • 缺点:如果任务增长过快,会创建大量线程,可能会造成 OOM(Out of Memory)异常。

3. SingleThreadExecutor

//创建一个单线程线程池,顺序执行多个任务。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SingleThreadExecutorExample {
    public static void main(String[] args) {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        
        for (int i = 1; i <= 5; i++) {
            final int task = i;
            singleThreadExecutor.execute(() -> {
                System.out.println("执行任务 " + task + ",线程:" + Thread.currentThread().getName());
            });
        }
        
        singleThreadExecutor.shutdown();
    }
}
  • 特点:创建单线程化的线程池,始终只有一个工作线程。
  • 适用场景:适用于需要保证任务顺序执行的场景,避免多线程并发的复杂性。
  • 优点:可以保证任务按顺序执行,适合单一任务队列。
  • 缺点:性能较低,不适合需要高并发的场景。

4. ScheduledThreadPool

//创建一个支持定时和周期性执行任务的线程池,示例任务每隔 2 秒执行一次,共执行 3 次。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {
    public static 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 引入)

//创建一个基于任务分解的线程池来并行执行多个任务,适合处理需要拆分的小任务。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class WorkStealingPoolExample {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService workStealingPool = Executors.newWorkStealingPool(); // 创建默认线程数为CPU核心数的工作窃取线程池
        
        for (int i = 1; i <= 8; i++) {
            final int task = 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 利用率 并行计算和多任务的分解

专栏推荐

大佬们可以收藏以备不时之需:

Spring Boot 专栏:http://t.csdnimg.cn/peKde

ChatGPT 专栏:http://t.csdnimg.cn/cU0na

Java 专栏:http://t.csdnimg.cn/YUz5e

Go 专栏:http://t.csdnimg.cn/Jfryo

Netty 专栏:http://t.csdnimg.cn/0Mp1H

Redis 专栏:http://t.csdnimg.cn/JuTue

Mysql 专栏:http://t.csdnimg.cn/p1zU9

架构之路 专栏:http://t.csdnimg.cn/bXAPS

csdn-end

博主深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新JAVA全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

这套1T的JAVA学习资料是为真正想在技术道路上突围的人准备的,内容覆盖全面:从各大厂的面试题到1000多个专业简历模板,从就业班到进阶课程,再到架构师实战与全栈高薪课程,帮助你从基础到高阶一步步提升!

无论是找工作还是技能进阶,这份VIP资料都是你不可错过的利器!

部分内容:

1

2

3

8

9

10

如有需要加下方V了解详情,备注:JAVA开发VIP资料。

猜你喜欢

转载自blog.csdn.net/jinxinxin1314/article/details/143276342