Java线程池使用示例:自定义线程池(ThreadPoolExecutor)

Java线程池使用示例

下面我将展示如何使用自定义线程池(ThreadPoolExecutor)来执行任务,包括提交Runnable任务、Callable任务,处理拒绝策略以及关闭线程池。

import java.util.concurrent.*;

public class ThreadPoolDemo {
    
    // 自定义线程工厂(为线程命名)
    static class CustomThreadFactory implements ThreadFactory {
        private int count = 0;
        
        @Override
        public Thread newThread(Runnable r) {
            count++;
            Thread thread = new Thread(r);
            thread.setName("Custom-Thread-" + count);
            thread.setDaemon(false); // 设置为非守护线程
            return thread;
        }
    }

    public static void main(String[] args) throws Exception {
        // 创建线程池
        ExecutorService customPool = new ThreadPoolExecutor(
            3,                            // 核心线程数
            6,                            // 最大线程数
            5, TimeUnit.SECONDS,          // 非核心线程空闲5秒销毁
            new ArrayBlockingQueue<>(5),   // 有界队列(容量5)
            new CustomThreadFactory(),     // 自定义线程工厂
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );

        System.out.println("提交15个任务到线程池:");
        System.out.println("队列容量=5,最大线程=6 -> 最多同时处理11个任务");

        // 提交15个任务(超出最大处理能力)
        for (int i = 1; i <= 15; i++) {
            final int taskId = i;
            customPool.submit(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 执行任务-" + taskId);
                    // 模拟任务执行时间
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 提交有返回值的任务
        Future<String> future = customPool.submit(() -> {
            System.out.println(Thread.currentThread().getName() + " 执行Callable任务");
            Thread.sleep(800);
            return "任务执行成功!";
        });

        try {
            System.out.println("\nCallable任务结果: " + future.get(2, TimeUnit.SECONDS));
        } catch (TimeoutException e) {
            System.err.println("任务超时未完成");
        } catch (ExecutionException e) {
            System.err.println("任务执行异常: " + e.getCause());
        }

        // 等待所有任务基本完成
        Thread.sleep(1500);
        
        // 关闭线程池(优雅关闭)
        shutdownThreadPool(customPool);
    }
    
    // 优雅关闭线程池的方法
    private static void shutdownThreadPool(ExecutorService pool) {
        try {
            System.out.println("\n正在关闭线程池...");
            pool.shutdown(); // 拒绝新任务
            
            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
                System.out.println("强制终止运行中的任务...");
                pool.shutdownNow(); // 尝试终止正在执行的任务
            }
            
            System.out.println("线程池已关闭");
        } catch (InterruptedException e) {
            System.err.println("关闭线程池时被中断: " + e.getMessage());
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

使用说明

1. 线程池关键参数

  • 核心线程数:3个
  • 最大线程数:6个(当队列满时,会创建新线程直到6个)
  • 任务队列:容量为5的有限队列(ArrayBlockingQueue
  • 拒绝策略CallerRunsPolicy(当队列满且线程数达最大值时,由调用线程自己执行任务)

2. 线程池工作流程

graph TD
    A[提交任务] --> B{是否超过核心线程数?}
    B --> |否| C[创建核心线程执行]
    B --> |是| D{队列是否已满?}
    D --> |否| E[任务入队列等待]
    D --> |是| F{线程数是否达到最大?}
    F --> |否| G[创建新线程执行]
    F --> |是| H[触发拒绝策略]

3. 拒绝策略的行为示例

  • 在代码中我们提交了15个任务,但最大处理能力只有11个
  • 超出能力后:
    • 第12-15个任务将由CallerRunsPolicy策略处理
    • 调用submit()的主线程(main)会直接执行这些任务
  • 执行时会看到main线程执行任务的输出

4. 最佳实践建议

  1. 任务提交

    • 使用execute()提交不需要返回值的任务
    • 使用submit()提交需要返回值的任务
    • 使用invokeAll()提交批量任务
  2. 异常处理

    • 在任务内捕获所有异常
    • 使用Future.get()捕获执行异常
  3. 优雅关闭

    • shutdown(): 停止接受新任务,继续执行队列中的任务
    • awaitTermination(timeout): 等待执行完成
    • shutdownNow(): 尝试中断所有任务
  4. 监控线程池

ThreadPoolExecutor executor = (ThreadPoolExecutor) customPool;
System.out.println("活跃线程数: " + executor.getActiveCount());
System.out.println("已完成任务数: " + executor.getCompletedTaskCount());
System.out.println("队列大小: " + executor.getQueue().size());

这个示例完整展示了线程池的使用方式,包括自定义线程工厂、提交任务、获取结果、异常处理和优雅关闭的完整流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值