分布式微服务系统架构第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. 定期评估和调优线程池配置

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

相关推荐
好奇的菜鸟1 小时前
如何在IntelliJ IDEA中设置数据库连接全局共享
java·数据库·intellij-idea
DuelCode2 小时前
Windows VMWare Centos Docker部署Springboot 应用实现文件上传返回文件http链接
java·spring boot·mysql·nginx·docker·centos·mybatis
优创学社22 小时前
基于springboot的社区生鲜团购系统
java·spring boot·后端
幽络源小助理2 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
猴哥源码2 小时前
基于Java+springboot 的车险理赔信息管理系统
java·spring boot
YuTaoShao3 小时前
【LeetCode 热题 100】48. 旋转图像——转置+水平翻转
java·算法·leetcode·职场和发展
ai小鬼头3 小时前
AIStarter如何助力用户与创作者?Stable Diffusion一键管理教程!
后端·架构·github
Dcs3 小时前
超强推理不止“大”——手把手教你部署 Mistral Small 3.2 24B 大模型
java
东阳马生架构3 小时前
订单初版—1.分布式订单系统的简要设计文档
java
Code blocks4 小时前
使用Jenkins完成springboot项目快速更新
java·运维·spring boot·后端·jenkins