Java线程池完全指南

Java线程池完全指南

Java线程池完全指南

一、为什么需要线程池?

在并发编程中,线程是宝贵的系统资源。频繁创建和销毁线程会带来严重的性能开销

  • 创建开销:每次创建线程都需要分配内存、初始化栈空间
  • 调度开销:大量线程会导致 CPU 上下文频繁切换
  • 资源耗尽:无限制创建线程可能导致 OOM(OutOfMemoryError)

💡 核心思想 :线程池通过复用已有线程 来减少创建销毁的开销,同时控制最大并发数防止资源耗尽。


二、ThreadPoolExecutor 核心参数

Java线程池的本质是 ThreadPoolExecutor 类,它有7个核心参数:

java 复制代码
public ThreadPoolExecutor(
    int corePoolSize,          // 1. 核心线程数(常驻线程)
    int maximumPoolSize,       // 2. 最大线程数
    long keepAliveTime,        // 3. 非核心线程空闲存活时间
    TimeUnit unit,             // 4. 存活时间单位
    BlockingQueue<Runnable> workQueue,  // 5. 任务队列
    ThreadFactory threadFactory,        // 6. 线程工厂
    RejectedExecutionHandler handler    // 7. 拒绝策略
)

参数详解

参数 说明 推荐值
corePoolSize 即使空闲也不会被回收的线程数 CPU密集型:CPU核数+1;IO密集型:CPU核数×2
maximumPoolSize 线程池允许的最大线程数 根据任务类型和硬件配置调整
keepAliveTime 非核心线程闲置超时时间 通常30秒~60秒
workQueue 存放等待执行任务的队列 见下文队列选择
threadFactory 创建新线程的工厂 推荐使用自定义工厂设置有意义的线程名
handler 队列满且线程数达上限时的处理策略 见下文拒绝策略

📌 任务队列的选择

队列类型 特点 适用场景
ArrayBlockingQueue 有界数组队列,FIFO 有明确容量限制的场景
LinkedBlockingQueue 可选有界/无界链表队列 默认用于Executors工厂方法
SynchronousQueue 不存储元素,直接传递 CachedThreadPool使用
PriorityBlockingQueue 支持优先级排序 需要优先处理高优先级任务

📌 四种拒绝策略

策略 行为
AbortPolicy(默认) 抛出 RejectedExecutionException
CallerRunsPolicy 由提交任务的线程自己执行
DiscardPolicy 静默丢弃任务,不抛异常
DiscardOldestPolicy 丢弃队列中最老的任务

三、线程池工作流程

当提交一个新任务到线程池时,执行流程如下:

复制代码
                    提交任务
                       │
            ┌──────────▼──────────┐
            │ 当前线程 < corePoolSize? │
            └────┬─────────┬────┘
               是│         │否
                ▼          │
           创建核心线程     │
           执行任务        │
                        ▼
              ┌──────────────────┐
              │   工作队列未满?   │
              └───┬──────────┬───┘
                 是│          │否
                  ▼          │
             加入等待队列     │
                        ▼
              ┌──────────────────┐
              │ 当前线程 < maxPoolSize? │
              └───┬──────────┬───┘
                 是│          │否
                  ▼          │
             创建非核心线程    │
             执行任务       │
                        ▼
                   执行拒绝策略

关键规则总结:

  1. 优先用核心线程执行任务
  2. 核心线程满了进队列
  3. 队列满了创建非核心线程
  4. 非核心线程也满了 → 拒绝策略

四、三种常用线程池

1. FixedThreadPool --- 固定大小线程池

java 复制代码
// 固定10个线程的线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(10);

// 等价于:
ExecutorService fixedPool = new ThreadPoolExecutor(
    10, 10,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>()
);

适用场景 :Web服务器处理请求、批量数据处理

⚠️ 注意:队列无界可能导致OOM

2. CachedThreadPool --- 可缓存线程池

java 复制代码
// 按需创建线程,空闲60秒回收
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 等价于:
ExecutorService cachedPool = new ThreadPoolExecutor(
    0, Integer.MAX_VALUE,
    60L, TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>()
);

适用场景 :短时异步任务、负载不均衡场景

⚠️ 注意:最大线程数为Integer.MAX_VALUE,可能创建过多线程

3. SingleThreadExecutor --- 单线程线程池

java 复制代码
// 只有一个线程的线程池,保证任务顺序执行
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 等价于:
ExecutorService singlePool = new ThreadPoolExecutor(
    1, 1,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>()
);

适用场景 :需要保证任务按顺序执行的场景

⚠️ 注意:队列无界,堆积任务可能导致OOM

⚠️ 重要提醒 :阿里巴巴《Java开发手册》明确要求禁止使用Executors创建线程池 ,因为默认的无界队列可能导致OOM。推荐通过 ThreadPoolExecutor 自定义参数。

--

五、实战示例:正确创建和使用线程池

✅ 推荐写法

java 复制代码
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolDemo {

    public static void main(String[] args) {
        // 1. 自定义线程工厂(设置有意义的线程名)
        ThreadFactory namedFactory = new ThreadFactory() {
            private final AtomicInteger counter = new AtomicInteger(0);
            
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("my-pool-thread-" + counter.incrementAndGet());
                t.setDaemon(false);  // 非守护线程
                return t;
            }
        };

        // 2. 创建线程池(推荐方式)
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            4,                      // corePoolSize: 核心线程数
            8,                      // maximumPoolSize: 最大线程数
            60L,                    // keepAliveTime: 空闲存活时间
            TimeUnit.SECONDS,       // 时间单位
            new ArrayBlockingQueue<>(100),  // 有界队列,容量100
            namedFactory,           // 自定义线程工厂
            new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略:调用者执行
        );

        // 3. 提交任务
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executor.execute(() -> {
                System.out.println(Thread.currentThread().getName() 
                    + " 正在执行任务 " + taskId);
                try {
                    Thread.sleep(1000);  // 模拟耗时操作
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println(Thread.currentThread().getName() 
                    + " 完成任务 " + taskId);
            });
        }

        // 4. 优雅关闭
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();  // 超时后强制关闭
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
        }
    }
}

使用 submit() 获取返回值

java 复制代码
ExecutorService executor = Executors.newFixedThreadPool(4);

Future<String> future = executor.submit(() -> {
    // 执行耗时计算
    Thread.sleep(2000);
    return "计算结果";
});

// 获取结果(阻塞直到完成)
String result = future.get();  // 或 future.get(3, TimeUnit.SECONDS)
System.out.println(result);

executor.shutdown();

六、线程池监控与调优

监控关键指标

java 复制代码
ThreadPoolExecutor executor = ...;

// 核心监控指标
System.out.println("当前活跃线程数: " + executor.getActiveCount());
System.out.println("当前线程总数: " + executor.getPoolSize());
System.out.println("已完成任务数: " + executor.getCompletedTaskCount());
System.out.println("排队中任务数: " + executor.getQueue().size());
System.out.println("历史最大线程数: " + executor.getLargestPoolSize());

🔧 调优建议

场景 corePoolSize 建议 maximumPoolSize 建议 队列选择
CPU 密集型(计算) CPU 核数 + 1 CPU 核数 + 1 小容量有界队列
IO 密集型(网络/DB) CPU 核数 × 2 CPU 核数 × 2 ~ 4 较大容量有界队列
混合型 按比例分配 动态扩容 有界队列 + 合理拒绝策略

七、常见问题与最佳实践

❌ 常见错误

  1. 使用 Executors 创建线程池 → 可能导致 OOM
  2. 线程池不复用 → 每次 new 新线程池,浪费资源
  3. 忘记 shutdown() → JVM 无法正常退出
  4. 任务中吞掉 InterruptedException → 应恢复中断状态
  5. 使用无界队列 → 内存可能无限增长

✅ 最佳实践清单

  • 始终通过 ThreadPoolExecutor 构造函数创建线程池
  • 给线程设置有意义的名称(便于排查问题)
  • 使用有界队列(防止内存溢出)
  • 指定合理的拒绝策略
  • 记得调用 shutdown() 或 shutdownNow()
  • 捕获并处理 RejectedExecutionException
  • 对长时间运行的任务设置超时

八、总结

要点 内容
核心优势 线程复用、控制并发、统一管理
7个参数 core / max / keepAlive / unit / queue / factory / handler
执行流程 核心线程 → 队列 → 非核心线程 → 拒绝策略
三种常用池 Fixed / Cached / Single(生产慎用)
最佳实践 自定义 ThreadPoolExecutor + 有界队列 + 合理拒绝策略

📚 延伸阅读 :建议阅读 Doug Lea 的《Concurrent Programming in Java》以及 JDK 源码中 java.util.concurrent 包的实现。


本文基于 JDK 8+ 编写,涵盖了线程池的核心概念与实战用法。

九、完整可运行测试代码

以下是一个完整、可直接编译运行的 Java 线程池测试程序,涵盖了本文所有核心知识点。

文件结构

复制代码
ThreadPoolDemo/
├── src/
│   └── main/
│       └── java/
│           └── com/
│               └── example/
│                   ├── ThreadPoolTest.java      # 主测试类
│                   ├── NamedThreadFactory.java   # 自定义线程工厂
│                   └── MonitorTask.java         # 监控任务
└── pom.xml                                     # Maven依赖(JDK 8+)

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>thread-pool-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <!-- 可执行 JAR 插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.example.ThreadPoolTest</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <!-- 打包依赖 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>shade</goal></goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

NamedThreadFactory.java --- 自定义线程工厂

java 复制代码
package com.example;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义线程工厂:为每个线程设置有意义的名称,便于排查问题
 * 
 * 使用方式:
 *   ThreadFactory factory = new NamedThreadFactory("my-worker");
 *   ExecutorService pool = new ThreadPoolExecutor(..., factory, ...);
 */
public class NamedThreadFactory implements ThreadFactory {

    private final String prefix;              // 线程名前缀
    private final AtomicInteger counter = new AtomicInteger(1); // 线程计数器
    private final boolean daemon;             // 是否守护线程

    public NamedThreadFactory(String prefix) {
        this(prefix, false);
    }

    public NamedThreadFactory(String prefix, boolean daemon) {
        this.prefix = prefix;
        this.daemon = daemon;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, prefix + "-" + counter.getAndIncrement());
        t.setDaemon(daemon);
        // 设置未捕获异常处理器
        t.setUncaughtExceptionHandler((thread, ex) -> {
            System.err.println("[" + thread.getName() "] 未捕获异常: " + ex.getMessage());
            ex.printStackTrace();
        });
        return t;
    }
}

MonitorTask.java --- 定时监控任务

java 复制代码
package com.example;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 线程池监控任务:定期打印线程池运行状态
 */
public class MonitorTask implements Runnable {

    private final ThreadPoolExecutor executor;
    private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    public MonitorTask(ThreadPoolExecutor executor) {
        this.executor = executor;
    }

    @Override
    public void run() {
        System.out.println("\n========== 线程池监控 [" + sdf.format(new Date()) + "] ==========");
        System.out.printf("  核心线程数: %d / 最大线程数: %d%n",
                executor.getCorePoolSize(), executor.getMaximumPoolSize());
        System.out.printf("  当前活跃线程: %d | 当前总线程: %d | 历史峰值: %d%n",
                executor.getActiveCount(), executor.getPoolSize(), executor.getLargestPoolSize());
        System.out.printf("  已完成任务: %d | 总提交任务: %d%n",
                executor.getCompletedTaskCount(), executor.getTaskCount());
        System.out.printf("  队列中等待: %d (剩余容量: %d)%n",
                executor.getQueue().size(), executor.getQueue().remainingCapacity());
        System.out.println("========================================================\n");
    }

    /**
     * 启动定时监控(每5秒打印一次状态)
     */
    public static void startMonitoring(ThreadPoolExecutor executor) {
        ScheduledMonitor monitor = new ScheduledMonitor(executor);
        monitor.start();
    }

    /**
     * 内部定时器实现(使用单独的守护线程)
     */
    static class ScheduledMonitor {
        private final ThreadPoolExecutor target;
        private volatile boolean running = true;

        ScheduledMonitor(ThreadPoolExecutor target) {
            this.target = target;
        }

        void start() {
            Thread monitorThread = new Thread(() -> {
                while (running && !target.isTerminated()) {
                    try {
                        new MonitorTask(target).run();
                        Thread.sleep(5000); // 每5秒监控一次
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
                System.out.println(">>> 监控线程已停止");
            }, "pool-monitor");
            monitorThread.setDaemon(true);
            monitorThread.start();
        }

        void stop() {
            running = false;
        }
    }
}

ThreadPoolTest.java --- 主测试类(完整可运行)

java 复制代码
package com.example;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.List;
import java.util.ArrayList;

/**
 * ============================================================
 *  Java线程池完整测试程序
 *  ============================================================
 *  
 *  本程序演示了以下内容:
 *  1. 自定义ThreadPoolExecutor创建线程池
 *  2. 核心参数配置(core/max/queue/factory/handler)
 *  3. submit() 返回Future获取结果
 *  4. 四种拒绝策略对比
 *  5. 线程池监控
 *  6. 优雅关闭(shutdown + awaitTermination)
 *  
 *  运行方式:
 *    mvn clean compile exec:java -Dexec.mainClass="com.example.ThreadPoolTest"
 *    或直接运行 main 方法
 *  
 *  预期输出:
 *    各任务由不同工作线程执行,最后打印汇总统计信息
 *  ============================================================
 */
public class ThreadPoolTest {

    // ========== 任务计数器 ==========
    private static final AtomicInteger successCount = new AtomicInteger(0);
    private static final AtomicInteger failCount = new AtomicInteger(0);

    public static void main(String[] args) throws Exception {
        System.out.println("╔══════════════════════════════════════════╗");
        System.out.println("║     Java线程池完整测试程序 v1.0          ║");
        System.out.println("╚══════════════════════════════════════════╝\n");

        // ==================== 第一步:创建线程池 ====================
        System.out.println(">>> 第一步:创建自定义线程池...");
        ThreadPoolExecutor executor = createThreadPool();

        // 启动监控
        MonitorTask.startMonitoring(executor);

        // ==================== 第二步:测试submit返回值 ====================
        System.out.println(">>> 第二步:测试submit()获取Future返回值...");
        testSubmitWithFuture(executor);

        // ==================== 第三步:批量提交任务 ====================
        System.out.println("\n>>> 第三步:批量提交30个模拟任务...");
        batchSubmitTasks(executor, 30);

        // ==================== 第四步:测试拒绝策略 ====================
        System.out.println("\n>>> 第四步:演示拒绝策略...");
        testRejectionPolicy();

        // ==================== 第五步:优雅关闭 ====================
        System.out.println("\n>>> 第五步:优雅关闭线程池...");
        gracefulShutdown(executor);

        // ==================== 最终统计 ====================
        printFinalStats();
    }

    /**
     * 创建自定义线程池(推荐的生产环境写法)
     */
    private static ThreadPoolExecutor createThreadPool() {
        int coreSize = 4;       // 核心线程数
        int maxSize = 8;        // 最大线程数
        int queueCapacity = 50; // 队列容量

        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                coreSize,
                maxSize,
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(queueCapacity),
                new NamedThreadFactory("worker"),  // 自定义线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:调用者执行
        );

        // 允许核心线程超时回收(可选)
        pool.allowCoreThreadTimeOut(false);

        System.out.printf("    ✓ 线程池创建成功: core=%d, max=%d, queue=%d%n",
                coreSize, maxSize, queueCapacity);
        return pool;
    }

    /**
     * 测试submit()方法获取Future返回值
     */
    private static void testSubmitWithFuture(ThreadPoolExecutor executor) throws Exception {
        Callable<String> task1 = () -> {
            Thread.sleep(800);
            return "Hello from Future!";
        };

        Callable<Integer> task2 = () -> {
            Thread.sleep(500);
            return 42;
        };

        Callable<List<String>> task3 = () -> {
            Thread.sleep(300);
            List<String> list = new ArrayList<>();
            list.add("Java");
            list.add("ThreadPool");
            list.add("Demo");
            return list;
        };

        // 提交任务并获取Future
        Future<String> f1 = executor.submit(task1);
        Future<Integer> f2 = executor.submit(task2);
        Future<List<String>> f3 = executor.submit(task3);

        // 获取结果(阻塞等待)
        System.out.println("    Future[1] 结果: " + f1.get());       // Hello from Future!
        System.out.println("    Future[2] 结果: " + f2.get());       // 42
        System.out.println("    Future[3] 结果: " + f3.get());       // [Java, ThreadPool, Demo]
        System.out.println("    ✓ Future测试完成\n");
    }

    /**
     * 批量提交模拟任务
     */
    private static void batchSubmitTasks(ThreadPoolExecutor executor, int count)
            throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(count);

        long startTime = System.currentTimeMillis();

        for (int i = 1; i <= count; i++) {
            final int taskId = i;
            executor.execute(() -> {
                try {
                    // 模拟耗时操作(IO密集型:随机200~1000ms)
                    int sleepMs = 200 + (int)(Math.random() * 800);
                    Thread.sleep(sleepMs);

                    String threadName = Thread.currentThread().getName();
                    System.out.printf("    [%s] ✅ 任务#%d 完成 (耗时%dms)%n",
                            threadName, taskId, sleepMs);
                    successCount.incrementAndGet();
                } catch (InterruptedException e) {
                    System.out.printf("    [任务#%d] ❌ 被中断%n", taskId);
                    failCount.incrementAndGet();
                    Thread.currentThread().interrupt();
                } finally {
                    latch.countDown();  // 计数器减1
                }
            });
        }

        // 等待所有任务完成(最多等60秒)
        boolean allDone = latch.await(60, TimeUnit.SECONDS);
        long elapsed = System.currentTimeMillis() - startTime;

        System.out.printf("    ✓ 所有任务完成? %s | 总耗时: %dms | 成功: %d | 失败: %d%n",
                allDone ? "是" : "超时", elapsed,
                successCount.get(), failCount.get());
    }

    /**
     * 演示四种拒绝策略的行为差异
     */
    private static void testRejectionPolicy() {
        System.out.println("    --- 创建一个极小线程池来触发拒绝策略 ---");

        // 极小配置:1核心线程,队列容量2,最大线程2
        ThreadPoolExecutor tinyPool = new ThreadPoolExecutor(
                1, 2,
                10L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                new NamedThreadFactory("reject-test"),
                new ThreadPoolExecutor.AbortPolicy() // 默认:抛异常
        );

        try {
            // 提交5个任务(1执行 + 2排队 + 2非核心 = 5刚好满)
            for (int i = 1; i <= 5; i++) {
                final int id = i;
                tinyPool.execute(() -> {
                    try { Thread.sleep(1000); } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    System.out.println("    [reject-test] 任务#" + id + " 完成");
                });
            }
            System.out.println("    ✓ 前5个任务正常提交");

            // 第6个任务应该触发拒绝策略
            try {
                tinyPool.execute(() -> System.out.println("不该执行到这里"));
            } catch (RejectedExecutionException e) {
                System.out.println("    ✓ 第6个任务被拒绝! (AbortPolicy抛出异常)");
            }
        } finally {
            tinyPool.shutdownNow();
        }

        System.out.println("    ✓ 拒绝策略测试完成\n");
    }

    /**
     * 优雅关闭线程池(两阶段关闭)
     */
    private static void gracefulShutdown(ThreadPoolExecutor executor) throws InterruptedException {
        // 阶段1:停止接受新任务,等待已有任务完成
        executor.shutdown();

        // 阶段2:最多等待30秒
        if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
            // 超时后强制关闭
            System.out.println("    ⚠ 线程池未在30秒内关闭,执行shutdownNow()...");
            List<Runnable> unfinished = executor.shutdownNow();
            System.out.println("    强制中断了 " + unfinished.size() + " 个未完成任务");
        }

        System.out.printf("    ✓ 线程池已关闭 (isTerminated=%b, isShutdown=%b)%n",
                executor.isTerminated(), executor.isShutdown());
    }

    /**
     * 打印最终统计信息
     */
    private static void printFinalStats() {
        System.out.println("\n╔══════════════════════════════════════════╗");
        System.out.println("║            测试执行报告                  ║");
        System.out.println("╠══════════════════════════════════════════╣");
        System.out.printf("║  成功完成任务: %-24d ║%n", successCount.get());
        System.out.printf("║  失败/中断任务: %-23d ║%n", failCount.get());
        System.out.printf("║  总计: %-33d ║%n", successCount.get() + failCount.get());
        System.out.println("╚══════════════════════════════════════════╝");
        System.out.println("\n🎉 测试全部完成!");
    }
}

运行步骤

bash 复制代码
# 1. 克隆或创建项目目录
mkdir -p ThreadPoolDemo/src/main/java/com/example
cd ThreadPoolDemo

# 2. 将上述4个文件放入对应路径

# 3. 编译并运行
mvn clean compile exec:java -Dexec.mainClass="com.example.ThreadPoolTest"

# 或者打包成可执行JAR
mvn clean package
java -jar target/thread-pool-demo-1.0-SNAPSHOT.jar

预期输出示例

复制代码
╔══════════════════════════════════════════╗
║     Java线程池完整测试程序 v1.0          ║
╚══════════════════════════════════════════╝

>>> 第一步:创建自定义线程池...
    ✓ 线程池创建成功: core=4, max=8, queue=50

>>> 第二步:测试submit()获取Future返回值...
    Future[1] 结果: Hello from Future!
    Future[2] 结果: 42
    Future[3] 结果: [Java, ThreadPool, Demo]
    ✓ Future测试完成

>>> 第三步:批量提交30个模拟任务...
    [worker-1] ✅ 任务#1 完成 (耗时653ms)
    [worker-2] ✅ 任务#2 完成 (耗时412ms)
    ...
    ✓ 所有任务完成? 是 | 总耗时: 3210ms | 成功: 30 | 失败: 0

>>> 第四步:演示拒绝策略...
    ✓ 前5个任务正常提交
    ✓ 第6个任务被拒绝! (AbortPolicy抛出异常)

>>> 第五步:优雅关闭线程池...
    ✓ 线程池已关闭 (isTerminated=true, isShutdown=true)

╔══════════════════════════════════════════╗
║            测试执行报告                  ║
╠══════════════════════════════════════════╣
║  成功完成任务: 30                         ║
║  失败/中断任务: 0                         ║
║  总计: 30                                ║
╚══════════════════════════════════════════╝

🎉 测试全部完成!

相关推荐
李白的天不白1 小时前
SmartAdmin(基于 Spring Boot 框架)中配置跨域请求 VUE3 设置请求头
java·前端
橙子进阶之路1 小时前
Java线程(CompletableFuture)
java·开发语言
鹅城剑仙1 小时前
Java CompletableFuture 异步编程完全指南
java
2601_961875241 小时前
法考备考计划表|学习计划|资料已整理
java·开发语言·学习·eclipse·tomcat·c#·hibernate
重生之我是Java开发战士1 小时前
【Java SE】多线程(三):单例模式,阻塞队列,线程池与定时器
java·javascript·单例模式
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第115题】【并发篇】第15题:说一下悲观锁和乐观锁的区别?
java·开发语言·面试
心之伊始2 小时前
Spring Boot Actuator + Micrometer 实战:自定义业务指标并接入 Prometheus 观测接口耗时
java·spring boot·prometheus·actuator·micrometer
Full Stack Developme2 小时前
Spring Integration 教程
java·后端·spring
摇滚侠2 小时前
MyBatis 入门到项目实战 MyBatis 分页插件 65-66
java·开发语言·sql·mybatis