当前位置: 首页 > article >正文

Java如何自定义线程池

目录

1、前言

2、Executors不推荐使用的原因

3、ThreadPoolExecutor的7个核心参数

1、corePoolSize   核心线程数

2、maximumPoolSize  最大核心线程数

3、keepAliveTime  最长等待时间

4、TimeUnit    时间单位

5、workQueue   阻塞队列

6、threadFactory   线程工厂

7、RejectedExecutionHandler  拒绝策略

3、总结


1、前言

大家在工作中,可能创建线程池用的比较多的方式,就是使用java.util.concurrent包下的Executors进行创建线程池。

但是这样创建并不是最好的方式,阿里巴巴Java开发手册是不推荐使用的,因为Executors提供的方法会默认一些配置参数,有时候可能并不是我们想要的,比如最大线程数量、线程等待时间、线程等待时间单位、阻塞队列、拒绝策略等,会有时候也需要业务场景以及资源、性能的考虑,推荐使用ThreadPoolExecutor自定义线程池,这样可以根据我们的需求和资源考虑,进行设置自定义线程池的7个参数。

2、Executors不推荐使用的原因

1、有OOM的潜在风险

比如Executors中的方法newFixedThreadPool和newSingleThreadExecutor,阻塞队列都是使用了LinkedBlockingQueue,如果我们进入到他的源码,可以看到如下代码

    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

它的长度是int类型的最大值,即2的31次方-1,可以想象如果生产速度大于队列的消费速度,队列会一直增长,有OOM内存溢出的风险。

2、配置不够灵活

因为Executors中的方法都只需要传递一个线程数量,其他的参数都是底层声明好了,如果开发人员想根据服务器的硬件资源的情况进行配置核心线程数和最大线程数量,或者想制定其他的拒绝策略,都是比较棘手的。

3、ThreadPoolExecutor的7个核心参数

  //自定义线程工厂
        ThreadFactory threadFactory = new ThreadFactory() {
            AtomicInteger integer = new AtomicInteger(1);

            @Override
            public Thread newThread(@NotNull Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("MyThread-" + integer.incrementAndGet());
                return thread;
            }
        };
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                5,
                10,
                2000,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(10),
                threadFactory,
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );

1、corePoolSize   核心线程数

线程池核心线程数的大小,即最小能够保证存活的线程数,即便这些线程在空闲状态,也不会被回收(设置核心线程允许超时过期除外)

2、maximumPoolSize  最大核心线程数

最大线程数量,线程池中核心线程数不够用的情况下,可以根据最大核心线程数进行扩展,防止资源耗尽导致性能问题。

3、keepAliveTime  最长等待时间

线程的过期时间,指的是除corePoolSize核心线程数,其余的线程数。如果等待新的任务到来的时间超过的该值,这些线程则会被回收。

4、TimeUnit    时间单位

最长等待时间的时间单位。

比如枚举TimeUnit 中的TimeUnit.SECONDS(秒)

TimeUnit.MILLISECONDS(毫秒)

5、workQueue   阻塞队列

即等待的线程队列,用于保存待执行的任务,可以是ArrayBlockingQueue、LinkedBlockingQueue等。

6、threadFactory   线程工厂

创建线程的工厂,默认为Executors.defaultThreadFactory(),可以自定义线程工厂new ThreadFactory,重写newThread方法,自己定义创建线程的逻辑和属性。

7、RejectedExecutionHandler  拒绝策略

当任务队列已满或者已关闭,新的任务无法提交到线程池中时的处理方式。内置了以下拒绝策略:

默认为AbortPolicy:直接拒绝,抛出异常。

CallerRunsPolicy:由调用者线程处理该任务。

DiscardPolicy:直接抛弃。

DiscardOldestPolicy:抛弃掉队列中最老的任务,提交当前任务。

3、总结

使用ThreadPoolExecutor自定义线程池有以下好处与优点:

  1. 线程管理:能够方便地控制线程的数量,避免资源的浪费和线程过多导致的性能问题。

  2. 提高系统的响应速度:通过线程池预先创建线程,可以减少线程创建和销毁的开销,提高任务的响应速度。

  3. 提高系统的稳定性:通过线程池可以控制线程的创建数量,避免线程数量过多导致系统崩溃的问题。

  4. 提高资源利用率:线程池可以复用线程,减少线程创建和销毁的开销,提高系统的资源利用率。

  5. 控制任务的执行顺序:可以通过线程池的工作队列来控制任务的执行顺序,保证任务按照一定的顺序执行。

  6. 提供更多的扩展性:线程池提供了丰富的配置选项,可以根据需求调整线程池的参数,满足不同的业务需求。

总之,使用ThreadPoolExecutor自定义线程池可以提高系统的性能、稳定性和资源利用率,同时还提供了更灵活的线程管理和任务控制能力。

今天是1024程序员节,祝各位程序猿们节日快乐,今天没有BUG!


http://www.kler.cn/news/363998.html

相关文章:

  • 苹果瑕疵数据集苹果质量数据集YOLO格式VOC格式 深度学习 目标检测 数据集
  • QImage和QPixmap
  • Ubutu下的Python如何打包
  • 项目管理的主要内容包括哪些,项目工具有哪些
  • 【系统配置】命令行修改统信UOS的grub启动延时
  • Scala的trait特质
  • Python + 查看个人下载次数小工具 - 记录
  • 【.Net】【C#】Program.cs通用代码模板
  • AJAX中get和post的区别
  • 【自动化测试之oracle数据库】MacOs如何安装oracle- client
  • Matlab|电价负荷需求响应-考虑电价变动
  • 线性可分支持向量机的原理推导 9-25对拉格朗日函数L(w,b,α) 关于w求导 公式解析
  • 深入浅出神经网络:从基础原理到高级应用
  • mysql 13 MySQL基于规则的优化
  • 解决ElasticSearch启动成功却无法在浏览器访问问题
  • 解决:git SSL certificate problem: unable to get local issuer certificate
  • 孤岛架构在异构性方面优势
  • 国内 Docker 镜像加速与 GitHub 加速服务:CNPROXY.TOP
  • Spring 设计模式之工厂模式
  • 分类任务中评估模型性能的核心指标
  • HTTP协议解析(http/1、2、3)
  • 【uniapp版即时通讯】IM社交交友聊天语音视频通话双端APP+搭建视频教程
  • 028.爬虫专用浏览器-抓取#shadowRoot(closed)下的内容
  • C#与C++交互开发系列(九):字符串传递的几种形式
  • 执行Django项目的数据库迁移命令时报错:(1050, “Table ‘django_session‘ already exists“);如何破?
  • 【spring cloud】深入探讨 集群,分布式,微服务