Java中ThreadPool线程池的详细使用指南

发布于:2025-08-08 ⋅ 阅读:(56) ⋅ 点赞:(0)

Java中ThreadPool线程池的详细使用指南

核心是在保证线程安全的情况下提速。线程池能够有效管理线程生命周期,避免频繁创建和销毁线程带来的性能开销,同时控制并发线程数量防止系统资源耗尽。

一 、任务主体不存在外部参数传入

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {

    public static void main(String[] args) {
        // 定义任务数量为100个
        int taskNum = 100;
        // 创建CountDownLatch用于等待所有任务完成,参数为任务数量
        final CountDownLatch latch = new CountDownLatch(taskNum);
        // 创建固定大小的线程池,包含10个工作线程
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
        
        // 提交任务到线程池
        for (int i = 0; i < taskNum; i++) {
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 执行具体任务逻辑
                        executeTask();
                    } catch (Exception e) {
                        // 捕获异常并记录日志
                        insertLog(e.getMessage());
                    } finally {
                        // 无论任务成功与否,都减少计数器
                        latch.countDown();
                    }
                }
            });
        }
        
        // 关闭线程池,不再接受新任务
        fixedThreadPool.shutdown();
        
        try {
            // 等待所有任务完成,最多阻塞当前线程
            latch.await();
        } catch (InterruptedException e) {
            // 处理中断异常
            insertLog(e.getMessage());
        }
        
        System.out.println("所有任务执行完成");
        // 这里可以添加任务完成后的后续处理代码
    }

    /**
     * 执行主体任务方法,不存在外部数据传入
     * 示例:可以执行一些独立的任务,如生成报表、处理独立数据等
     */
    public static void executeTask() {
        System.out.println("正在执行独立任务...");
        // 实际业务逻辑代码
    }

    /**
     * 记录日志方法
     * @param message 需要记录的日志信息
     */
    public static void insertLog(String message) {
        System.out.println("记录日志:" + message);
        // 实际日志记录逻辑,如写入文件或数据库
    }
}

二、存在传入参数的情况

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ParameterizedThreadPoolExample {
    
    public static void main(String[] args) {
        // 模拟创建需要执行的任务数据
        List<String> dataList = new ArrayList<>();
        for (int j = 1; j <= 5; j++) {
            dataList.add("任务数据" + j);
        }
        
        // 任务数量和线程池大小
        int taskNum = 5, poolNum = 5;
        List<Runnable> taskList = new ArrayList<>();
        
        // 创建任务列表
        for (int i = 0; i < taskNum; i++) {
            // 要传入线程的参数必须是final或effectively final
            final String data = dataList.get(i);
            taskList.add(new Runnable() {
                @Override
                public void run() {
                    // 执行带参数的任务
                    executeTask(data);
                }
            });
        }
        
        // 执行任务列表
        executeTasks(taskList, taskNum, poolNum);
    }
    
    /**
     * 封装的线程池执行方法
     * @param taskList 任务列表
     * @param taskNum 任务数量
     * @param poolNum 线程池大小
     */
    public static void executeTasks(List<Runnable> taskList, Integer taskNum, Integer poolNum) {
        // 创建计数器
        final CountDownLatch latch = new CountDownLatch(taskNum);
        // 创建固定大小线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(poolNum);
        
        // 提交任务到线程池
        for (final Runnable task : taskList) {
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 执行任务
                        task.run();
                    } catch (Exception e) {
                        // 异常处理
                        insertLog(e.getMessage());
                    } finally {
                        // 计数器减一
                        latch.countDown();
                    }
                }
            });
        }
        
        // 关闭线程池
        fixedThreadPool.shutdown();
        
        try {
            // 等待所有任务完成
            latch.await();
        } catch (InterruptedException e) {
            insertLog(e.getMessage());
        }
        
        System.out.println("所有任务执行完成");
    }
    
    /**
     * 执行带参数的任务
     * @param data 传入的任务数据
     */
    public static void executeTask(String data) {
        System.out.println("正在处理任务数据:" + data);
        // 实际业务处理逻辑
    }
    
    /**
     * 记录日志方法
     * @param message 日志信息
     */
    public static void insertLog(String message) {
        System.out.println("错误日志:" + message);
    }
}

三、带超时控制的线程池使用

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TimeoutThreadPoolExample {
    
    public static void main(String[] args) {
        // 模拟创建任务数据
        List<String> dataList = new ArrayList<>();
        for (int j = 1; j <= 5; j++) {
            dataList.add("任务数据" + j);
        }
        
        // 任务数量和线程池大小
        int taskNum = 5, poolNum = 5;
        List<Runnable> taskList = new ArrayList<>();
        
        // 创建任务列表
        for (int i = 0; i < taskNum; i++) {
            final String data = dataList.get(i);
            taskList.add(new Runnable() {
                @Override
                public void run() {
                    executeTask(data);
                }
            });
        }
        
        // 执行带超时控制的线程池任务
        executeTasksWithTimeout(taskList, taskNum, poolNum);
    }
    
    /**
     * 带超时控制的线程池执行方法
     * @param taskList 任务列表
     * @param taskNum 任务数量
     * @param poolNum 线程池大小
     */
    public static void executeTasksWithTimeout(List<Runnable> taskList, Integer taskNum, Integer poolNum) {
        // 创建固定大小线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(poolNum);
        
        // 提交所有任务
        for (final Runnable task : taskList) {
            fixedThreadPool.execute(task);
        }
        
        // 关闭线程池
        fixedThreadPool.shutdown();
        
        try {
            // 设置超时等待,1表示1个单位,TimeUnit.HOURS表示单位是小时
            // 最多等待1小时,要么提前执行完结束,要么超时返回
            boolean isSuccess = fixedThreadPool.awaitTermination(1, TimeUnit.HOURS);
            
            // 处理超时情况
            if(!isSuccess){
                System.out.println("线程执行超时,执行超时处理逻辑");
                // 可以添加强制终止线程池的逻辑
                // fixedThreadPool.shutdownNow();
            }
        } catch (InterruptedException e) {
            insertLog(e.getMessage());
        }
        
        System.out.println("所有任务执行完成");
    }
    
    /**
     * 执行带参数的任务
     * @param data 任务数据
     */
    public static void executeTask(String data) {
        System.out.println("处理任务:" + data);
        try {
            // 模拟任务执行时间
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 记录日志方法
     * @param message 日志信息
     */
    public static void insertLog(String message) {
        System.out.println("系统日志:" + message);
    }
}

使用场景说明

  1. 无参数任务:适用于批量处理独立任务,如生成报表、发送通知等
  2. 带参数任务:适用于处理不同输入数据的任务,如处理不同用户请求、转换不同文件等
  3. 带超时控制:适用于对执行时间有要求的场景,如接口调用、定时任务等

注意事项

  1. 线程池大小应根据系统资源和任务特性合理设置
  2. 传入线程的参数必须是final或effectively final
  3. 超时时间应根据实际业务需求合理设置
  4. 注意异常处理和资源释放
  5. 对于长时间运行的任务,应考虑添加中断机制

网站公告

今日签到

点亮在社区的每一天
去签到