分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南


title: java线程池使用 author: 哪吒 date: '2023-06-15'

点击勘误issues,哪吒感谢大家的阅读

Java线程池使用指南

1. 线程池基础使用

1.1 创建线程池的方式

方式一:使用Executors工具类(不推荐)
go 复制代码
// 1. 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);

// 2. 缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 3. 单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 4. 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);

为什么不推荐使用Executors?

go 复制代码
问题分析:
┌─────────────────────────────────────────────────────────┐
│  newFixedThreadPool & newSingleThreadExecutor          │
│  ↓                                                     │
│  使用LinkedBlockingQueue(无界队列)                    │
│  ↓                                                     │
│  可能导致内存溢出(OOM)                                │
│                                                         │
│  newCachedThreadPool                                    │
│  ↓                                                     │
│  最大线程数为Integer.MAX_VALUE                          │
│  ↓                                                     │
│  可能创建大量线程导致系统崩溃                            │
└─────────────────────────────────────────────────────────┘
方式二:手动创建ThreadPoolExecutor(推荐)
go 复制代码
public class ThreadPoolFactory {
    
    /**
     * 创建标准线程池
     */
    public static ThreadPoolExecutor createStandardPool() {
        returnnew ThreadPoolExecutor(
            5,                                      // 核心线程数
            10,                                     // 最大线程数
            60L,                                    // 空闲时间
            TimeUnit.SECONDS,                       // 时间单位
            new ArrayBlockingQueue<>(100),          // 工作队列
            new ThreadFactory() {                   // 线程工厂
                privatefinal AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "CustomPool-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);  // 设置为用户线程
                    t.setPriority(Thread.NORM_PRIORITY);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );
    }
}

2. 常用线程池类型及应用场景

2.1 CPU密集型任务线程池

go 复制代码
public class CPUIntensiveThreadPool {
    
    /**
     * CPU密集型任务线程池配置
     * 核心线程数 = CPU核心数 + 1
     */
    public static ThreadPoolExecutor createCPUIntensivePool() {
        int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
        returnnew ThreadPoolExecutor(
            corePoolSize,
            corePoolSize,
            0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(50),
            new ThreadFactory() {
                privatefinal AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "CPU-Pool-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.AbortPolicy()
        );
    }
    
    // 使用示例:计算密集型任务
    public static void main(String[] args) {
        ThreadPoolExecutor executor = createCPUIntensivePool();
        
        // 提交计算任务
        for (int i = 0; i < 10; i++) {
            finalint taskId = i;
            executor.submit(() -> {
                long result = fibonacci(35); // 计算斐波那契数列
                System.out.println("任务" + taskId + "计算结果:" + result + 
                    " - 线程:" + Thread.currentThread().getName());
            });
        }
        
        shutdownGracefully(executor);
    }
    
    private static long fibonacci(int n) {
        if (n <= 1) return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
    
    private static void shutdownGracefully(ExecutorService executor) {
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

2.2 IO密集型任务线程池

go 复制代码
public class IOIntensiveThreadPool {
    
    /**
     * IO密集型任务线程池配置
     * 核心线程数 = CPU核心数 * 2
     */
    public static ThreadPoolExecutor createIOIntensivePool() {
        int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
        returnnew ThreadPoolExecutor(
            corePoolSize,
            corePoolSize * 2,
            60L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(200),
            new ThreadFactory() {
                privatefinal AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "IO-Pool-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }
    
    // 使用示例:文件读写任务
    public static void main(String[] args) {
        ThreadPoolExecutor executor = createIOIntensivePool();
        
        // 提交IO任务
        for (int i = 0; i < 20; i++) {
            finalint taskId = i;
            executor.submit(() -> {
                try {
                    // 模拟文件读写操作
                    Thread.sleep(1000); // 模拟IO等待
                    System.out.println("任务" + taskId + "完成文件操作 - 线程:" + 
                        Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        shutdownGracefully(executor);
    }
    
    private static void shutdownGracefully(ExecutorService executor) {
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

2.3 定时任务线程池

go 复制代码
public class ScheduledThreadPoolExample {
    
    public static void main(String[] args) throws InterruptedException {
        ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(
            3,
            new ThreadFactory() {
                privatefinal AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "Scheduler-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            }
        );
        
        // 1. 延迟执行任务
        scheduler.schedule(() -> {
            System.out.println("延迟3秒执行的任务 - " + new Date());
        }, 3, TimeUnit.SECONDS);
        
        // 2. 固定频率执行任务
        ScheduledFuture<?> fixedRateTask = scheduler.scheduleAtFixedRate(() -> {
            System.out.println("每2秒执行一次的任务 - " + new Date());
        }, 1, 2, TimeUnit.SECONDS);
        
        // 3. 固定延迟执行任务
        ScheduledFuture<?> fixedDelayTask = scheduler.scheduleWithFixedDelay(() -> {
            System.out.println("上次执行完成后延迟1秒再执行 - " + new Date());
            try {
                Thread.sleep(500); // 模拟任务执行时间
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, 1, 1, TimeUnit.SECONDS);
        
        // 运行10秒后停止
        Thread.sleep(10000);
        fixedRateTask.cancel(false);
        fixedDelayTask.cancel(false);
        
        scheduler.shutdown();
    }
}

3. 线程池监控与管理

3.1 线程池状态监控

go 复制代码
public class ThreadPoolMonitor {
    
    /**
     * 创建可监控的线程池
     */
    public static ThreadPoolExecutor createMonitorablePool() {
        returnnew ThreadPoolExecutor(
            5, 10, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(100),
            new ThreadFactory() {
                privatefinal AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "Monitor-Pool-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
        ) {
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                System.out.println("任务开始执行 - 线程:" + t.getName());
            }
            
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                if (t != null) {
                    System.err.println("任务执行异常:" + t.getMessage());
                } else {
                    System.out.println("任务执行完成");
                }
            }
            
            @Override
            protected void terminated() {
                super.terminated();
                System.out.println("线程池已终止");
            }
        };
    }
    
    /**
     * 打印线程池状态信息
     */
    public static void printPoolStatus(ThreadPoolExecutor executor) {
        System.out.println("\n=== 线程池状态信息 ===");
        System.out.println("核心线程数:" + executor.getCorePoolSize());
        System.out.println("最大线程数:" + executor.getMaximumPoolSize());
        System.out.println("当前线程数:" + executor.getPoolSize());
        System.out.println("活跃线程数:" + executor.getActiveCount());
        System.out.println("队列中任务数:" + executor.getQueue().size());
        System.out.println("已完成任务数:" + executor.getCompletedTaskCount());
        System.out.println("总任务数:" + executor.getTaskCount());
        System.out.println("是否关闭:" + executor.isShutdown());
        System.out.println("是否终止:" + executor.isTerminated());
        System.out.println("========================\n");
    }
}

3.2 线程池异常处理

go 复制代码
public class ThreadPoolExceptionHandling {
    
    /**
     * 创建带异常处理的线程池
     */
    public static ThreadPoolExecutor createSafeThreadPool() {
        returnnew ThreadPoolExecutor(
            5, 10, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(50),
            new ThreadFactory() {
                privatefinal AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "Safe-Pool-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    // 设置未捕获异常处理器
                    t.setUncaughtExceptionHandler((thread, ex) -> {
                        System.err.println("线程 " + thread.getName() + " 发生未捕获异常:" + ex.getMessage());
                        ex.printStackTrace();
                    });
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }
    
    /**
     * 安全任务包装器
     */
    public static Runnable wrapTask(Runnable task) {
        return () -> {
            try {
                task.run();
            } catch (Exception e) {
                System.err.println("任务执行异常:" + e.getMessage());
                e.printStackTrace();
                // 可以在这里添加异常上报逻辑
            }
        };
    }
    
    public static void main(String[] args) {
        ThreadPoolExecutor executor = createSafeThreadPool();
        
        // 提交可能抛异常的任务
        executor.submit(wrapTask(() -> {
            System.out.println("正常任务执行");
        }));
        
        executor.submit(wrapTask(() -> {
            thrownew RuntimeException("模拟任务异常");
        }));
        
        // 使用Future处理异常
        Future<?> future = executor.submit(() -> {
            thrownew RuntimeException("Future异常");
        });
        
        try {
            future.get();
        } catch (ExecutionException e) {
            System.err.println("通过Future捕获异常:" + e.getCause().getMessage());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        executor.shutdown();
    }
}

4. 最佳实践与注意事项

4.1 线程池参数配置指南

go 复制代码
public class ThreadPoolConfigGuide {
    
    /**
     * 根据任务类型配置线程池
     */
    publicstaticclass ThreadPoolConfigurator {
        
        // CPU密集型任务配置
        public static ThreadPoolExecutor forCPUIntensive() {
            int processors = Runtime.getRuntime().availableProcessors();
            returnnew ThreadPoolExecutor(
                processors,                    // 核心线程数 = CPU核心数
                processors,                    // 最大线程数 = CPU核心数
                0L, TimeUnit.MILLISECONDS,     // 无空闲时间
                new ArrayBlockingQueue<>(processors * 2), // 队列大小适中
                new ThreadPoolExecutor.AbortPolicy()
            );
        }
        
        // IO密集型任务配置
        public static ThreadPoolExecutor forIOIntensive() {
            int processors = Runtime.getRuntime().availableProcessors();
            returnnew ThreadPoolExecutor(
                processors * 2,                // 核心线程数 = CPU核心数 * 2
                processors * 4,                // 最大线程数 = CPU核心数 * 4
                60L, TimeUnit.SECONDS,         // 空闲60秒回收
                new LinkedBlockingQueue<>(1000), // 较大的队列
                new ThreadPoolExecutor.CallerRunsPolicy()
            );
        }
        
        // 混合型任务配置
        public static ThreadPoolExecutor forMixed() {
            int processors = Runtime.getRuntime().availableProcessors();
            returnnew ThreadPoolExecutor(
                processors + 1,                // 核心线程数 = CPU核心数 + 1
                processors * 2,                // 最大线程数 = CPU核心数 * 2
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(200),
                new ThreadPoolExecutor.CallerRunsPolicy()
            );
        }
    }
}

4.2 常见问题与解决方案

go 复制代码
public class ThreadPoolTroubleshooting {
    
    /**
     * 问题1:线程池任务积压
     * 解决方案:动态调整线程池大小
     */
    publicstaticclass DynamicThreadPool {
        privatefinal ThreadPoolExecutor executor;
        privatefinal ScheduledExecutorService monitor;
        
        public DynamicThreadPool(ThreadPoolExecutor executor) {
            this.executor = executor;
            this.monitor = Executors.newSingleThreadScheduledExecutor();
            startMonitoring();
        }
        
        private void startMonitoring() {
            monitor.scheduleAtFixedRate(() -> {
                int queueSize = executor.getQueue().size();
                int activeCount = executor.getActiveCount();
                int corePoolSize = executor.getCorePoolSize();
                int maxPoolSize = executor.getMaximumPoolSize();
                
                // 队列积压严重,增加线程
                if (queueSize > 100 && activeCount >= corePoolSize * 0.8) {
                    int newCoreSize = Math.min(corePoolSize + 1, maxPoolSize);
                    if (newCoreSize > corePoolSize) {
                        executor.setCorePoolSize(newCoreSize);
                        System.out.println("增加核心线程数至:" + newCoreSize);
                    }
                }
                
                // 队列空闲,减少线程
                if (queueSize < 10 && activeCount < corePoolSize * 0.5 && corePoolSize > 2) {
                    executor.setCorePoolSize(corePoolSize - 1);
                    System.out.println("减少核心线程数至:" + (corePoolSize - 1));
                }
            }, 0, 30, TimeUnit.SECONDS);
        }
    }
    
    /**
     * 问题2:任务执行时间过长
     * 解决方案:任务超时控制
     */
    publicstaticclass TimeoutTaskExecutor {
        privatefinal ThreadPoolExecutor executor;
        
        public TimeoutTaskExecutor(ThreadPoolExecutor executor) {
            this.executor = executor;
        }
        
        public <T> T executeWithTimeout(Callable<T> task, long timeout, TimeUnit unit) 
                throws InterruptedException, ExecutionException, TimeoutException {
            Future<T> future = executor.submit(task);
            try {
                return future.get(timeout, unit);
            } catch (TimeoutException e) {
                future.cancel(true); // 取消任务
                throw e;
            }
        }
    }
}

4.3 性能优化建议

go 复制代码
线程池性能优化清单:

1. 参数配置优化
   ✓ 根据任务类型选择合适的核心线程数
   ✓ 设置合理的最大线程数和队列大小
   ✓ 选择适当的拒绝策略

2. 任务设计优化
   ✓ 避免任务执行时间过长
   ✓ 合理拆分大任务
   ✓ 避免任务间的强依赖关系

3. 监控与调优
   ✓ 定期监控线程池状态
   ✓ 记录任务执行时间
   ✓ 根据监控数据调整参数

4. 资源管理
   ✓ 及时关闭线程池
   ✓ 避免创建过多线程池
   ✓ 合理设置线程优先级

5. 总结

Java线程池是并发编程的重要工具,正确使用线程池可以:

  • 提高性能:减少线程创建和销毁的开销

  • 控制资源:限制并发线程数量,避免系统资源耗尽

  • 提高响应性:复用线程,快速响应任务请求

  • 便于管理:统一管理线程生命周期

关键要点

  1. 避免使用Executors创建线程池,推荐手动创建ThreadPoolExecutor

  2. 根据任务类型(CPU密集型/IO密集型)合理配置参数

  3. 实施有效的监控和异常处理机制

  4. 注意线程池的优雅关闭

  5. 定期评估和调优线程池配置

通过遵循这些最佳实践,可以充分发挥线程池的优势,构建高性能、稳定的并发应用程序。

相关推荐
无限进步_4 分钟前
【C++】验证回文字符串:高效算法详解与优化
java·开发语言·c++·git·算法·github·visual studio
亚历克斯神4 分钟前
Spring Cloud 2026 架构演进
java·spring·微服务
凌乱的豆包5 分钟前
Spring Cloud Alibaba Nacos 服务注册发现和分布式配置中心
分布式
七夜zippoe8 分钟前
Spring Cloud与Dubbo架构哲学对决
java·spring cloud·架构·dubbo·配置中心
海派程序猿8 分钟前
Spring Cloud Config拉取配置过慢导致服务启动延迟的优化技巧
java
阿维的博客日记19 分钟前
为什么不逃逸代表不需要锁,JIT会直接删掉锁
java
William Dawson20 分钟前
CAS的底层实现
java
九英里路31 分钟前
cpp容器——string模拟实现
java·前端·数据结构·c++·算法·容器·字符串
Gavin_ZYX34 分钟前
Skill 管理过于繁琐,不如写个自动同步的工具
人工智能·架构·github
YDS82936 分钟前
大营销平台 —— 抽奖前置规则过滤
java·spring boot·ddd