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:稳定可靠,适合负载均衡的场景

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

相关推荐
南极企鹅1 小时前
深入理解 MVCC:数据库并发控制的基石
java·数据库·mysql
凯瑟琳.奥古斯特2 小时前
力扣1235:加权区间调度最优解
java·python·算法·leetcode·职场和发展
_童年的回忆_2 小时前
【php】在linux下PHP安装amqp扩展
linux·开发语言·php
想不到ID了2 小时前
第八篇: 登录注册功能实现
java·javascript
AIMath~2 小时前
python中的uv命令揭秘
开发语言·python·uv
码语智行2 小时前
shp文件生成
java
弹简特2 小时前
【零基础学Python】06-Python模块和包、异常处理、文件常用操作
开发语言·python
x***r1512 小时前
Postman-win64-7.2.2-Setup安装步骤详解(附API接口测试与参数配置教程)
开发语言·lua
plainGeekDev2 小时前
AlertDialog → DialogFragment
android·java·kotlin