Java并发编程:Executors框架类深度解析

一、Executors框架概述

在Java并发编程中,Executors是一个工具类,位于java.util.concurrent包下,它提供了创建线程池的静态工厂方法。合理使用线程池可以有效控制系统中并发线程的数量,避免因频繁创建和销毁线程带来的性能开销。

Executors框架的核心优势

  • 资源复用:避免频繁创建和销毁线程的开销

  • 统一管理:集中管理线程的生命周期和任务分配

  • 提升响应速度:任务到达时无需等待线程创建即可执行


二、三大核心线程池详解

1. newCachedThreadPool ------ 可缓存线程池

特点说明
  • 线程池长度超过处理需要时,可灵活回收空闲线程

  • 若无可回收线程,则新建线程

  • 适用于执行大量短期异步任务的场景

核心特性
特性 说明
核心线程数 0
最大线程数 Integer.MAX_VALUE
空闲线程存活时间 60秒
工作队列 SynchronousQueue
代码示例
java 复制代码
public class ThreadPoolTest2 {

    /**
     * newCachedThreadPool 创建一个可缓存线程池,
     * 如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
     */
    public static void test_2() {
        // 创建可缓存线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        
        for (int i = 0; i < 10; i++) {
            final int index = i;
            
            cachedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() 
                        + " 执行任务: " + index 
                        + " 当前时间: " + new Date().getSeconds());
                }
            });
        }
        
        // 注意:这里需要关闭线程池,否则程序不会结束
        cachedThreadPool.shutdown();
    }

    public static void main(String[] args) {
        test_2();
    }
}
运行特点
  • 线程会被复用,控制台输出中可能看到同一个线程名执行了多个任务

  • 空闲60秒后线程会自动回收

  • 适合处理生命周期短、执行频率高的任务


2. newSingleThreadExecutor ------ 单线程化线程池

特点说明
  • 只会用唯一的工作线程来执行所有任务

  • 保证所有任务按照指定顺序执行

  • 支持FIFO(先进先出)、LIFO(后进先出)、优先级等排序方式

核心特性
特性 说明
核心线程数 1
最大线程数 1
空闲线程存活时间 0秒
工作队列 LinkedBlockingQueue
代码示例
java 复制代码
public class ThreadPoolTest3 {

    /**
     * newSingleThreadExecutor 创建一个单线程化的线程池,
     * 它只会用唯一的工作线程来执行任务,
     * 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
     */
    public static void test_4() {
        // 创建单线程线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        
        for (int i = 1; i <= 10; i++) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    // 会按顺序打印 1,2,3,4,5,6,7,8,9,10
                    System.out.println(Thread.currentThread().getName() + " : " + index);
                    
                    // 模拟任务处理耗时
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        
        singleThreadExecutor.shutdown();
    }

    public static void main(String[] args) {
        test_4();
    }
}
运行特点
  • 所有任务都使用同一个线程执行

  • 任务严格按照提交顺序执行(FIFO)

  • 即使某个任务执行失败,线程池也会创建一个新线程继续执行后续任务

  • 适合需要保证顺序执行、不需要多线程并发的场景


3. newFixedThreadPool ------ 定长线程池

特点说明
  • 创建固定长度的线程池

  • 可控制线程最大并发数

  • 超出的线程会在队列中等待

  • 当线程池数量为1时,类似于单线程化线程池的效果

核心特性
特性 说明
核心线程数 nThreads(参数指定)
最大线程数 nThreads(参数指定)
空闲线程存活时间 0秒
工作队列 LinkedBlockingQueue
代码示例
java 复制代码
public class ThreadPoolTest4 {

    /**
     * newFixedThreadPool 创建一个定长线程池,
     * 可控制线程最大并发数,超出的线程会在队列中等待
     */
    public static void test_3() {
        // 创建固定大小为2的线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
        
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() 
                            + " 正在执行任务: " + index);
                        Thread.sleep(500); // 模拟任务执行
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        
        fixedThreadPool.shutdown();
    }
    
    /**
     * 演示当参数为1时的顺序执行效果
     * 此时类似于newSingleThreadExecutor
     */
    public static void test_order() {
        // 当参数为1时,可以控制线程的执行顺序,类似join的作用
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
        
        for (int i = 0; i < 5; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("顺序执行: " + index);
                }
            });
        }
        fixedThreadPool.shutdown();
    }

    public static void main(String[] args) {
        System.out.println("=== 固定2个线程的线程池 ===");
        test_3();
        
        // 等待上面的任务执行完毕
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("\n=== 固定1个线程的线程池(顺序执行) ===");
        test_order();
    }
}
运行特点
  • 线程池中的线程数量保持恒定

  • 当所有线程都在处理任务时,新任务会在队列中等待

  • 设置大小为1时,效果等同于newSingleThreadExecutor

  • 适合执行长期任务的场景


三、三种线程池对比

特性 newCachedThreadPool newSingleThreadExecutor newFixedThreadPool
核心线程数 0 1 nThreads
最大线程数 Integer.MAX_VALUE 1 nThreads
队列类型 SynchronousQueue LinkedBlockingQueue LinkedBlockingQueue
线程复用方式 动态创建和回收 固定单线程 固定数量线程
适用场景 短期异步任务 顺序执行任务 稳定负载任务
内存风险 高(可能创建过多线程) 中(队列可能堆积) 中(队列可能堆积)

四、使用注意事项

1. 关闭线程池

java 复制代码
// 使用完毕后必须关闭,否则程序不会退出
threadPool.shutdown();  // 优雅关闭
// 或
threadPool.shutdownNow(); // 立即关闭

2. 选择合适的线程池

  • 任务数量大且执行时间短newCachedThreadPool

  • 需要保证任务顺序执行newSingleThreadExecutor

  • 任务执行时间长且数量稳定newFixedThreadPool

3. 线程命名规范

java 复制代码
// 可以为线程设置有意义的名称,便于调试
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
    .setNameFormat("my-pool-%d").build();
ExecutorService pool = Executors.newFixedThreadPool(5, namedThreadFactory);

五、总结

Executors框架提供的三种线程池各有特点:

  1. newCachedThreadPool:弹性伸缩,适合突发性高、短期任务

  2. newSingleThreadExecutor:顺序执行,适合需要保证执行顺序的场景

  3. newFixedThreadPool:稳定可靠,适合负载均衡的场景

掌握这三种线程池的使用场景和特点,能够帮助我们在实际开发中选择最合适的并发处理方案,提升系统性能和稳定性。

相关推荐
程序猿大帅17 小时前
别再只当调包侠了:用 Spring AI 落地 Function Calling,我被大模型硬生生砸出了三个大坑
java
程序员晓琪18 小时前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly18 小时前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
众少成多积小致巨19 小时前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
东坡白菜19 小时前
破局全栈:前端开发的Java入门实战记录—JPA(2)
java·后端
SimonKing1 天前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
用户298698530141 天前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
小bo波2 天前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
nanxun8863 天前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103513 天前
Day01 | Java 基础(Java SE)
java