线程池ThreadPoolExecutor使用指南

在这里插入图片描述

线程池ThreadPoolExecutor使用指南

🧐使用线程池的好处是什么?

统一管理,减少资源获取创建的开销,提高利用率。

🔧线程池的参数

ThreadPoolExecutor​ 3 个最重要的参数:

  • corePoolSize​ : 任务队列未达到队列容量时,最大可以同时运行的线程数量。

  • maximumPoolSize​ : 任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。

  • workQueue​: 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中

ThreadPoolExecutor​其他常见参数 :

  • keepAliveTime​:线程池中的线程数量大于 corePoolSize​ 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime​才会被回收销毁。
  • unit​ : keepAliveTime​ 参数的时间单位。
  • threadFactory​ :executor 创建新线程的时候会用到。
  • handler​ :拒绝策略
🤔你是如何创建线程池的?为什么不建议直接用Executors​创建线程池?

一般不建议直接用Executors​创建线程池的,这种方式缓冲队列没有限制合适的大小(默认整形的最大值),处理不好会有OOM的风险。而是通过 ThreadPoolExecutor​ 构造函数的方式,这样的好处就是更加明确线程池的运行规则,规避资源耗尽的风险。

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }
✨线程池的策略有哪些?

当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时:

常见的策略有拒绝策略:

  • AbortPolicy​ 抛出 RejectedExecutionException​来拒绝新任务的处理。

  • CallerRunsPolicy​:调用执行自己的线程运行任务,由主线程自己来执行这个任务。(不允许丢弃任务适合该策略)

不常见策略(了解既可):

  • ThreadPoolExecutor.DiscardPolicy​:不处理新任务,直接丢弃掉。
  • ThreadPoolExecutor.DiscardOldestPolicy​:此策略将丢弃最早的未处理的任务请求。
📌Springboot下使用示例

当您使用ThreadPoolTaskExecutor​配置线程池时,可以参考以下示例代码:

ThreadPoolConfig​类通过@Configuration​注解标记为配置类,并定义了一个名为taskExecutor​的Bean,类型为ThreadPoolTaskExecutor​。在taskExecutor()​方法中,设置了线程池的核心线程数为10,最大线程数为20,队列容量为30,线程名前缀为"MyThread-",然后调用initialize()​方法初始化线程池,并返回配置好的ThreadPoolTaskExecutor​实例

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class ThreadPoolConfig {

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); // 设置核心线程数
        executor.setMaxPoolSize(20); // 设置最大线程数
        executor.setQueueCapacity(30); // 设置队列容量
        executor.setThreadNamePrefix("MyThread-"); // 设置线程名前缀
        executor.initialize(); // 初始化线程池
        return executor;
    }
}

异步任务的地方注入TaskExecutor Bean,并调用其execute()方法来提交任务:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    public void executeAsyncTask() {
        taskExecutor.execute(() -> {
            // 执行异步任务的逻辑
            System.out.println("Async task executed by thread: " + Thread.currentThread().getName());
        });
    }
}


然而,也有一些特殊场景下可能需要手动创建线程池实例:

  1. 定制化需求:如果需要对线程池进行高度定制,例如设置特定的线程池参数或使用特殊的线程工厂等,可能需要手动创建线程池实例。
  2. 独立使用:某些情况下,线程池只在一个特定的类或模块中使用,并且不需要在整个应用中共享,这时候手动创建线程池可能更合适。

大多数情况下建议将线程池实例交给Spring容器管理,以便统一管理和便于集成;如果手动创建了线程池实例,建议在某个特定的时机手动调用线程池的shutdown()​方法来优雅地关闭线程池,释放资源。

但这个特定时机怎么定义?使用CountDownLatch​或许可以符合你的场景。

CountDownLatch​的使用

CountDownLatch​ 的作用就是 允许 多个线程阻塞在一个地方,直到所有线程的任务都执行完毕。那么手动创建的线程就可以通过shutdown()​方法来优雅地关闭线程池了。

package com.fjh.demo.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * @ClassName: CustomThreadPoolExample
 * @Description: TODO 手动自定义创建线程池,CountDownLatch使用场景
 * @Author: fengjiahao
 * @Date: 2024/6/15 21:26
 */
public class CustomThreadPoolExample {

    public static void main(String[] args) throws InterruptedException {
        int numThreads = 5;
        // 核心线程数
        int corePoolSize = 3;
        // 最大线程数
        int maxPoolSize = 5;
        // 线程空闲时间
        long keepAliveTime = 10;
        // 任务队列,使用有界队列ArrayBlockingQueue
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize, // 核心线程数
                maxPoolSize, // 最大线程数
                keepAliveTime, // 线程空闲时间
                TimeUnit.SECONDS, // 时间单位
                new ArrayBlockingQueue<>(3) // 任务队列
        );
        CountDownLatch latch = new CountDownLatch(numThreads);
        for (int i = 0; i < numThreads; i++) {
            int finalI = i;
            executor.execute(() -> {
                try {
                    System.out.println("Thread【"+ finalI +"】 started execute: " + Thread.currentThread().getName());
                    Thread.sleep(2000); // 模拟线程执行任务
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally{
                    latch.countDown(); // 每个线程执行完成后调用countDown方法
                }
                System.out.println("Thread finished: " + Thread.currentThread().getName());
            });
        }
        latch.await(); // 等待所有线程执行完成
        System.out.println("All threads have finished. Continuing main thread.");
        executor.shutdown(); // 关闭线程池
    }
}

☕最后

其实java8中有更加优雅的方式处理这种场景CompletableFuture​,有兴趣的同学可以去了解下🙂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/713310.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统编程:基础IO

目录 1.C语言文件回顾 2.系统文件I/O 2.1 系统接口介绍 2.2 文件描述符fd 2.3 重定向 2.4 理解缓冲区 2.5 理解文件系统 1.C语言文件回顾 在学习系统文件的操作之前&#xff0c;还记得C语言是如何进行对文件的操作的吗&#xff1f;下面看C语言接口&…

浪潮信息打造业界首款50℃进液温度服务器 PUE逼近理论极限1.0!

在科技飞速发展的今天&#xff0c;浪潮信息以其前瞻性的技术创新思维&#xff0c;再次突破行业极限&#xff0c;推出业界首个支持50℃进液温度的浸没式液冷服务器NF5180G7。这一创新成果不仅展现了浪潮信息在液冷技术领域的深厚实力&#xff0c;更标志着服务器冷却技术的一次重…

【2024亲测无坑】在Centos.7虚拟机上安装Oracle 19C

目录 一、安装环境准备 1、linux虚拟机安装 2、虚拟机快照 3、空间检查&软件上传 二、Oracle软件安装 1.preinstall安装及其他配置准备 2.oracle安装 三、数据库实例的安装 1.netca——网络配置助手 2.dbca——数据库配置助手 四、ORACLE 19C 在linux centos 7上…

基于PPO的强化学习超级马里奥自动通关

目录 一、环境准备 二、训练思路 1.训练初期&#xff1a; 2.思路整理及改进&#xff1a; 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 思路四&#xff1a; 3.训练效果&#xff1a; 三、结果分析 四、完整代码 训练代码&#xff1a; 测试代码&#…

MySQL 日志(二)

本篇将继续介绍MySQL日志的相关内容 目录 一、二进制日志 简介 注意事项 删除二进制日志 查看二进制日志 二进制日志的格式 二、服务器日志维护 一、二进制日志 简介 二进制日志中主要记录了MySQL的更改事件&#xff08;不包含SELECT和SHOW),例如&#xff1a;表的…

Base64编码的工作原理与实际应用

目录 前言 一、什么是Base64编码&#xff1f; 二、Base64编码的原理 三、Base64编码的应用场景 四、为什么要使用Base 64 五、Base64加密解密的实现 前言 当你需要将二进制数据转换为可传输和存储的文本格式时&#xff0c;Base64编码是一个常用的选择。在这篇博客中&#…

C++ 51 之 继承中的构造和析构

对象构造和析构的调用原则 继承中的构造和析构 子类对象在创建时会首先调用父类的构造函数父类构造函数执行完毕后&#xff0c;才会调用子类的构造函数当父类构造函数有参数时&#xff0c;需要在子类初始化列表(参数列表)中显示调用父类构造函数析构函数调用顺序和构造函数相…

可以用来制作硬模空心耳机壳的胶粘剂有哪些种类?

可以用来制作硬模空心耳机壳的胶粘剂有哪些种类&#xff1f; 制作耳机壳的胶粘剂有很多种类&#xff0c;常见的有环氧树脂胶水、UV树脂胶、快干胶、热熔胶等。 这些胶粘剂都有不同的特点和适用场景&#xff0c;可以根据自己的需求选择合适的类型。 例如&#xff1a; 环氧树脂…

Adobe设计替代软件精选列表

Adobe软件的替代列表&#xff0c;最初由 XdanielArt 收集&#xff0c;并由社区改进。您可以随意打开问题或拉出请求&#xff0c;或从数据中创建图像(以便于共享)。列表总是按照免费和开源选项的顺序排列&#xff0c;但根据您的用例&#xff0c;它可能不是最佳选择 替代因素 &am…

Python 潮流周刊#56:NumPy 2.0 里更快速的字符串函数

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 本周刊由 Python猫 出品&#xff0c;精心筛选国内外的 250 信息源&#xff0c;为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景&#xff1a;帮助所有读者精进 Python 技术&am…

【linux】认识“文件”的本质,理解“文件系统”的设计逻辑,体会linux优雅的设计理念

⭐⭐⭐个人主页⭐⭐⭐ ~~~~~~~~~~~~~~~~~~ C站最❤❤❤萌❤❤❤博主 ~~~~~~~~~~~~~~~~~~~ ​♥东洛的克莱斯韦克-CSDN博客♥ ~~~~~~~~~~~~~~~~~~~~ 嗷呜~ ✌✌✌✌ 萌妹统治世界~ &#x1f389;&#x1f389;&#x1f389;&#x1f389; ✈✈✈✈相关文章✈✈✈✈ &#x1f4a…

2023年的Top20 AI应用在近一年表现怎么样?

AI应用现在进入寒武纪大爆发时代&#xff0c;百花争艳。如果倒回到2023年初&#xff0c;那时候排名靠前的AI应用在一年多时间&#xff0c;发生了哪些变化&#xff1f;能带给我们什么启示&#xff1f; 在2023年1月&#xff0c;排名靠前20的AI应用是&#xff1a; DeepL&#xff…

MATLAB中与直方图有关函数的关系

histogram Histogram plot画直方图 histcounts 直方图 bin 计数 histcounts是histogram的主要计算函数。 discretize 将数据划分为 bin 或类别 histogram2 画二元直方图 histcounts2 二元直方图 bin 计数 hist和histc过时了。替换不建议使用的 hist 和 histc 实例 hist → \r…

Day54 JDBC

Day54 JDBC JDBC&#xff1a;SUN公司提供的一套操作数据库的标准规范&#xff0c;就是使用Java语言操作关系型数据库的一套API JDBC与数据库驱动的关系&#xff1a;接口与实现的关系 给大家画一个jdbc的工作模式图 1.JDBC的四大金刚 1.DriverManager&#xff1a;用于注册驱动 2…

【Quartus 13.0】NIOS II 部署UART 和 PWM

打算在 EP1C3T144I7 芯片上部署 nios ii 做 uart & pwm控制 这个芯片或许不够做 QT 部署 这个芯片好老啊&#xff0c;但是做控制足够了&#xff0c;我只是想装13写 leader给的接口代码是用VHDL写的&#xff0c;我不会 当然verilog我也不太会 就这样&#xff0c;随便写吧 co…

SUSTAINABILITY,SCIESSCI双检期刊还能投吗?

本期&#xff0c;小编给大家介绍的是一本MDPI出版社旗下SCIE&SSCI双检“毕业神刊”——SUSTAINABILITY。据悉&#xff0c;早在2024年1月&#xff0c;ElSEVIER旗下的Scopus数据库已暂停收录检索期刊SUSTAINABILITY所发表文章&#xff0c;同时重新评估是否继续收录该期刊。随…

Qwen2——阿里巴巴最新的多语言模型挑战 Llama 3 等 SOTA

引言 经过几个月的期待&#xff0c; 阿里巴巴 Qwen 团队终于发布了 Qwen2 – 他们强大的语言模型系列的下一代发展。 Qwen2 代表了一次重大飞跃&#xff0c;拥有尖端的进步&#xff0c;有可能将其定位为 Meta 著名的最佳替代品 骆驼3 模型。在本次技术深入探讨中&#xff0c;我…

零基础入门学用Arduino 第三部分(三)

重要的内容写在前面&#xff1a; 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后&#xff0c;整体感觉是很好的&#xff0c;如果有条件的可以先学习一些相关课程&#xff0c;学起来会更加轻松&#xff0c;相关课程有数字电路…

python-基础篇-类与对象/面向对象程序设计-是什么

文章目录 定义一&#xff1a;面对对象是一种编程思想定义一&#xff1a;面向对象是一种抽象1、面向对象的两个基本概念2、面向对象的三大特性 定义一&#xff1a;你是土豪&#xff0c;全家都是土豪面向对象编程基础类和对象定义类创建和使用对象访问可见性问题面向对象的支柱 定…

C++初学者指南第一步---4.基本类型

C初学者指南第一步—4.基本类型 文章目录 C初学者指南第一步---4.基本类型1.变量声明2.快速概览Booleans 布尔型Characters 字符型Signed Integers 有符号整数Unsigned Integers 无符号整数Floating Point Types 浮点数类型 3.Common Number Representations 常用的数字表示常用…