随笔 - 547  文章 - 1  评论 - 292  阅读 - 33万

线程池ThreadPoolExecutor应用

线程池ThreadPoolExecutor应用

复制代码
package com.example.core.mydemo.threadPool;

import java.util.concurrent.*;

/**
 * link: https://www.cnblogs.com/oktokeep/p/18574975
 * 线程和线程池原理及demo演示
 *
 * output:
 * cpuCores=6
 * 任务
 * 任务
 * 任务
 * 任务
 * 任务
 * 任务
 * 任务
 * 任务
 * 任务
 * 任务
 * 执行任务1
 * 核心线程数:20
 * 队列大小:0
 * 执行任务2
 * 已完成任务数:11
 * 
 */
public class ExecutorsTest {
    public static void main(String[] args) {
        /**
         * 无界队列:newFixedThreadPool 使用的队列是 LinkedBlockingQueue,它是无界队列,任务堆积可能会导致内存溢出。
         * 线程无限增长:newCachedThreadPool 会无限创建线程,在任务量激增时可能耗尽系统资源。
         */
//        ExecutorService executor = Executors.newFixedThreadPool(2);

        /**
         * 解决办法: 推荐ThreadPoolExecutor
         * 使用 ThreadPoolExecutor,并明确指定参数:
         *
         * 这种配置在任务激增时,会创建大量线程,系统资源被耗尽。
         * 正确配置方式
         * 根据任务类型选择合理的线程数:
         * CPU 密集型:线程数建议设置为 CPU 核心数 + 1。
         * IO 密集型:线程数建议设置为 2 * CPU 核心数。
         */
        int cpuCores = Runtime.getRuntime().availableProcessors();
        System.out.println("cpuCores=" + cpuCores);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                1,   // 核心线程数
                1,   // 最大线程数
                60L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(100), // 有界队列    用有界队列,避免任务无限堆积。
                new ThreadPoolExecutor.AbortPolicy() // 拒绝策略    // 默认策略 当任务队列满时,线程池会触发拒绝策略,很多人不知道默认策略(AbortPolicy)会直接抛异常。
        );

        /**
         * new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
         * 改进:选择合适的策略
         * CallerRunsPolicy:提交任务的线程自己执行。
         * DiscardPolicy:直接丢弃新任务。
         * DiscardOldestPolicy:丢弃最老的任务。
         */

        /**
         * 改进方法
         * 减少任务的阻塞时间。
         * 增加核心线程数。
         * 使用异步非阻塞方式(如 NIO)。
         */
        executor.submit(() -> {
            try {
                Thread.sleep(10000); // 模拟阻塞任务
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {

                System.out.println("任务");
                try {
//                    throw new RuntimeException("任务异常");
//                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        //关闭线程池
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
        }


        ExecutorService executor2 = Executors.newSingleThreadExecutor();
        executor2.submit(() -> System.out.println("执行任务1"));
        executor2.shutdown();
        //某些场景直接使用 new Thread() 更简单。
        new Thread(() -> System.out.println("执行任务2")).start();

        //实时调整线程池参数,能适应业务的动态变化。
        executor.setCorePoolSize(20);
        executor.setMaximumPoolSize(50);

        //监控线程池状态   结合监控工具(如 JMX、Prometheus),实现实时监控。
        System.out.println("核心线程数:" + executor.getCorePoolSize());
        System.out.println("队列大小:" + executor.getQueue().size());
        System.out.println("已完成任务数:" + executor.getCompletedTaskCount());

    }
}
复制代码

 

posted on   oktokeep  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
历史上的今天:
2021-03-03 es创建索引及别名更新mapping方法 elasticsearch [nested] nested object under path [XXX] is not of nested type
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示