Java-实现可监控线程池

本文介绍了一个使用Spring Boot创建的线程池监控系统。该系统包括线程池创建、任务执行和实时监控等功能,并实现了线程池的状态监测及日志记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标:创建线程池和一个监控线程,监控线程持有线程池引用,接着定时打印线程池相关信息,使用springboot创建demo。
创建线程池接口:

/**
 * 通过设置的参数创建线程池
 * Created by wzx on 22/03/2019
 */
public interface ITestThreadPoolExecutorService {

    ThreadPoolExecutor createThreadPoolExecutor();

    int getCorePoolSize();

    void setCorePoolSize(int corePoolSize);

    int getMaxPoolSize();

    void setMaxPoolSize(int maxPoolSize);

    long getKeepAliveTime();

    void setKeepAliveTime(long keepAliveTime);

}

线程池实现类:

/**
 * Created by wzx on 22/03/2019
 */
@Data
public class TestThreadPoolExecutorService implements ITestThreadPoolExecutorService {

    private int corePoolSize;
    private int maxPoolSize;
    private long keepAliveTime;
    private int queueCapacity;
    private RejectedExecutionHandler rejectedExecutionHandler;

    @Override
    public ThreadPoolExecutor createThreadPoolExecutor() {
        return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, new ArrayBlockingQueue<>(getQueueCapacity()),
                getRejectedExecutionHandler());
    }

}

线程池监控接口:

/**
 * 线程池监控接口
 * Created by wzx on 22/03/2019
 */
public interface IThreadPoolMonitorService extends Runnable {

    void monitorThreadPool();

    ThreadPoolExecutor getExecutor();

    void setExecutor(ThreadPoolExecutor executor);

    long getMonitoringPeriod();

    void setMonitoringPeriod(long monitoringPeriod);

}

线程池监控实现类:


/**
 * Created by wzx on 22/03/2019
 */
@Data
public class ThreadPoolMonitorService implements IThreadPoolMonitorService {

    private Logger logger = LoggerFactory.getLogger(ThreadPoolMonitorService.class);

    private ThreadPoolExecutor executor;

    private long monitoringPeriod;

    @Override
    public void monitorThreadPool() {
        String buffer = "CurrentPoolSize:" + executor.getPoolSize() +
                " - CorePoolSize:" + executor.getCorePoolSize() +
                " - MaximumPoolSize:" + executor.getMaximumPoolSize() +
                " - ActiveTaskCount:" + executor.getActiveCount() +
                " - CompletedTaskCount:" + executor.getCompletedTaskCount() +
                " - TotalTaskCount:" + executor.getTaskCount() +
                " - isTerminated:" + executor.isTerminated();
        logger.debug(buffer);
    }

    @Override
    public void run() {
        try {
            while (true) {
                monitorThreadPool();
                Thread.sleep(monitoringPeriod * 1000);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }
}

线程池和线程池监控服务启动类:

/**
 * 这个类维护了线程池和线程池监控服务
 * Created by wzx on 22/03/2019
 */
@Component
public class ThreadPoolExecutorStarter {

    private Logger logger = LoggerFactory.getLogger(ThreadPoolExecutorStarter.class);

    @Autowired
    private ITestThreadPoolExecutorService threadPoolExecutorService;

    @Autowired
    private IThreadPoolMonitorService monitorService;

    public void start() {
        ThreadPoolExecutor executor = threadPoolExecutorService.createThreadPoolExecutor();
        executor.allowCoreThreadTimeOut(true);

        monitorService.setExecutor(executor);
        monitorService.setMonitoringPeriod(3);
        Thread monitor = new Thread(monitorService);
        monitor.start();

        for (int i = 1; i <= 10; i++) {
            executor.execute(new TestTask("task" + i));
        }

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }

        for (int i = 1; i <= 5; i++) {
            executor.execute(new TestTask("task" + i));
        }

        executor.shutdown();
    }


}

任务拒绝执行策略:

/**
 * Created by wzx on 22/03/2019
 */
public class TestRejectedExecutionHandler implements RejectedExecutionHandler {

    private Logger logger = LoggerFactory.getLogger(TestRejectedExecutionHandler.class);

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        logger.debug(r.toString() + ": has been rejected.");
    }

}

普通任务类:

/**
 * Created by wzx on 22/03/2019
 */
public class TestTask implements Runnable {

    private Logger logger = LoggerFactory.getLogger(TestTask.class);

    private String taskName;

    public TestTask(String taskName) {
        this.taskName = taskName;
    }

    @Override
    public void run() {
        try {
            logger.debug(taskName + " is started.");
            Thread.sleep(1000);
            logger.debug(taskName + " is completed.");
        } catch (InterruptedException e) {
            logger.error(taskName + " is not completed.");
            e.printStackTrace();
        }
    }

    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }

    public String getTaskName() {
        return taskName;
    }

    @Override
    public String toString() {
        return getTaskName();
    }
}

demo启动类:

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public TestRejectedExecutionHandler rejectedExecutionHandler() {
        return new TestRejectedExecutionHandler();
    }

    @Bean
    public ITestThreadPoolExecutorService threadPoolExecutorService(TestRejectedExecutionHandler rejectedExecutionHandler) {
        TestThreadPoolExecutorService executor = new TestThreadPoolExecutorService();
        executor.setCorePoolSize(1);
        executor.setMaxPoolSize(3);
        executor.setQueueCapacity(3);
        executor.setKeepAliveTime(10);
        executor.setRejectedExecutionHandler(rejectedExecutionHandler);
        return executor;
    }

    @Bean
    public IThreadPoolMonitorService monitorService() {
        ThreadPoolMonitorService monitorService = new ThreadPoolMonitorService();
        monitorService.setMonitoringPeriod(3);
        return monitorService;
    }

    @Autowired
    private ThreadPoolExecutorStarter executorStarter;

    @Override
    public void run(String... args) throws Exception {
        //线程池监控测试
        executorStarter.start();
    }
}

运行结果:

00:03:11.915 logback [Thread-10] DEBUG c.e.d.s.t.ThreadPoolMonitorService - CurrentPoolSize:0 - CorePoolSize:1 - MaximumPoolSize:3 - ActiveTaskCount:0 - CompletedTaskCount:0 - TotalTaskCount:0 - isTerminated:false
00:03:11.916 logback [restartedMain] DEBUG c.e.d.s.t.TestRejectedExecutionHandler - task7: has been rejected.
00:03:11.916 logback [pool-2-thread-3] DEBUG c.e.demo.service.threadpool.TestTask - task6 is started.
00:03:11.916 logback [pool-2-thread-1] DEBUG c.e.demo.service.threadpool.TestTask - task1 is started.
00:03:11.916 logback [pool-2-thread-2] DEBUG c.e.demo.service.threadpool.TestTask - task5 is started.
00:03:11.916 logback [restartedMain] DEBUG c.e.d.s.t.TestRejectedExecutionHandler - task8: has been rejected.
00:03:11.916 logback [restartedMain] DEBUG c.e.d.s.t.TestRejectedExecutionHandler - task9: has been rejected.
00:03:11.916 logback [restartedMain] DEBUG c.e.d.s.t.TestRejectedExecutionHandler - task10: has been rejected.
00:03:12.917 logback [pool-2-thread-3] DEBUG c.e.demo.service.threadpool.TestTask - task6 is completed.
00:03:12.917 logback [pool-2-thread-1] DEBUG c.e.demo.service.threadpool.TestTask - task1 is completed.
00:03:12.917 logback [pool-2-thread-2] DEBUG c.e.demo.service.threadpool.TestTask - task5 is completed.
00:03:12.917 logback [pool-2-thread-3] DEBUG c.e.demo.service.threadpool.TestTask - task2 is started.
00:03:12.917 logback [pool-2-thread-1] DEBUG c.e.demo.service.threadpool.TestTask - task3 is started.
00:03:12.917 logback [pool-2-thread-2] DEBUG c.e.demo.service.threadpool.TestTask - task4 is started.
00:03:13.918 logback [pool-2-thread-1] DEBUG c.e.demo.service.threadpool.TestTask - task3 is completed.
00:03:13.918 logback [pool-2-thread-3] DEBUG c.e.demo.service.threadpool.TestTask - task2 is completed.
00:03:13.918 logback [pool-2-thread-2] DEBUG c.e.demo.service.threadpool.TestTask - task4 is completed.
00:03:14.915 logback [Thread-10] DEBUG c.e.d.s.t.ThreadPoolMonitorService - CurrentPoolSize:3 - CorePoolSize:1 - MaximumPoolSize:3 - ActiveTaskCount:0 - CompletedTaskCount:6 - TotalTaskCount:6 - isTerminated:false
00:03:17.916 logback [Thread-10] DEBUG c.e.d.s.t.ThreadPoolMonitorService - CurrentPoolSize:3 - CorePoolSize:1 - MaximumPoolSize:3 - ActiveTaskCount:0 - CompletedTaskCount:6 - TotalTaskCount:6 - isTerminated:false

在Web应用中使用Java线程池,特别是`ScheduledThreadPoolExecutor`时,如果出现内存溢出和线程数持续增加的问题,通常与线程池的配置、任务管理以及生命周期控制不当有关。以下是一些最佳实践建议: ### 线程池配置原则 1. **合理设置核心线程数和最大线程数**:根据系统的处理能力和预期负载来设定这些参数。一般而言,在双核处理器上,若阻塞系数为0.9,则可能需要开启20个线程以充分利用CPU资源[^2]。 2. **适当调整keepAliveTime**:默认情况下,只有当线程池中的线程数超过corePoolSize时,keepAliveTime才会起作用。通过调用allowCoreThreadTimeOut方法可以让核心线程也遵循这个超时机制,有助于减少不必要的资源占用[^3]。 3. **选择合适的任务队列**:任务队列的选择会影响线程池的行为。例如,使用无界队列(如LinkedBlockingQueue)可能导致新提交的任务被无限排队,而不会创建新的工作线程去处理它们,除非达到最大线程数限制[^4]。 ### 内存泄漏预防措施 - **避免长期持有外部对象引用**:确保在线程池执行的任务中不保留对外部对象或类加载器的强引用,否则可能会导致这些对象无法被垃圾回收器回收,进而引发内存泄漏。 - **定期清理不再使用的定时任务**:对于`ScheduledThreadPoolExecutor`,应当注意及时取消那些已经完成或者不再需要的定时/周期性任务,并且要正确关闭线程池以释放所有相关资源。 ### 生命周期管理 - **优雅地关闭线程池**:使用shutdown()方法来停止接收新的任务,并等待已提交的任务执行完毕;必要时可使用awaitTermination()方法等待所有任务完成。若需立即终止所有正在执行的任务,可以考虑调用shutdownNow()方法[^4]。 - **监控线程池状态**:可以通过继承ThreadPoolExecutor并重写beforeExecute、afterExecute等方法来自定义监控逻辑,比如跟踪任务执行时间、统计异常信息等[^2]。 ### 示例代码 ```java // 创建一个固定大小的线程池 int corePoolSize = 10; int maximumPoolSize = 20; long keepAliveTime = 60L; TimeUnit unit = TimeUnit.SECONDS; ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, new LinkedBlockingQueue<Runnable>() ); // 提交任务 executor.execute(new MyTask()); // 关闭线程池 executor.shutdown(); // 或者 executor.shutdownNow(); ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值