首页 > 其他分享 >Springboot项目中如何使用线程池

Springboot项目中如何使用线程池

时间:2023-06-01 19:04:59浏览次数:46  
标签:Springboot 自定义 项目 int CompletableFuture executor 线程 ThreadPoolTaskExecutor


目录

1. 基于 ExecutorService 自定义线程池(Java 5中引入的)

2. 基于 ThreadPoolTaskExecutor 线程池的使用 (Spring提供,以及监听线程池)

3. 自定义 ThreadPoolTaskExecutor 线程池


用于大数据量的导出报表、远程请求处理数据量同步等等

日常项目中可以定义多个线程池,如:报表导出使用的线程池 或 大数据量操作时使用(在配合webSocket通知前端,再或者大文件上传的线程池)

导出大数据量Excel文件时,单个xlsx文件最大只能存储一百多万的数据行,假设有2000万的数据我们日常清空必定导出多个Excel文件,此时就可以使用本文章的案例。

1. 基于 ExecutorService 自定义线程池(Java 5中引入的)

Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下。

自定义线程池

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

    @Bean
    public ExecutorService callbackThreadPool() {
        ThreadFactory factory = new ThreadFactoryBuilder()
                .setUncaughtExceptionHandler((t, e) -> logger.error(t.getName() + " excute error:", e))
                .setNameFormat("callback-pool-%d").build();
        int corePoolSize = 3;
        int maxPoolSize = 4;
        long keepAliveTime = 5;
        ExecutorService pool = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MINUTES,
                new ArrayBlockingQueue<Runnable>(100000), factory, new ThreadPoolExecutor.CallerRunsPolicy());
        return pool;
    }

使用案例

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;

@RestController
@RequestMapping("thread")
public class ThreadPoolController {

    @Resource
    private ExecutorService callbackThreadPool;

    @GetMapping
    public Object thread(){
        
        // 不等待该线程执行结果
        callbackThreadPool.execute(() -> {
            // 代码块
        });


        // 等待所有线程都执行完,再执行后续操作
        List<String> dataList = Arrays.asList("123","456");

        CompletableFuture<?>[] cfs = new CompletableFuture[laoUserPartition.size()];
        int index = 0;
        for (String data : dataList) {
            // 每次循环创建一个线程
            CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
                // 线程内执行的操作

            }, callbackThreadPool);
            cfs[index++] = cf;
        }
        CompletableFuture.allOf(cfs).join();  // 此处等待监听的几个线程全部执行完      


        return 1;
    }



}

2. 基于 ThreadPoolTaskExecutor 线程池的使用 (Spring提供,以及监听线程池)

在springboot项目启动,如下查询加载的Bean

Springboot项目中如何使用线程池_后端

使用方法:

@RestController
public class PageController {

    @Autowired
    ThreadPoolTaskExecutor applicationTaskExecutor;  // applicationTaskExecutor 为spring注册时定义得 beanName


    // 开辟两个线程,后等待两个线程 都执行完的案例
    @GetMapping("/thread")
    public Object thread() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(() -> {
            for(int i = 0 ; i < 100000 ; i++){
                System.out.println("a-"+i);
            }
        }, applicationTaskExecutor);

        CompletableFuture<Void> completableFuture2 = CompletableFuture.runAsync(() -> {
            for(int i = 0 ; i < 100000 ; i++){
                System.out.println("w-"+i);
            }
        }, applicationTaskExecutor);
        
        // 等待这两个线程都执行完
        CompletableFuture.allOf(completableFuture1, completableFuture2).get();
        return "success";
    }
}

3. 自定义 ThreadPoolTaskExecutor 线程池

自定义设置线程的最大线程数等参数。

自定义Bean

@Bean
    public ThreadPoolTaskExecutor myThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //此方法返回可用处理器的虚拟机的最大数量; 不小于1
        //int core = Runtime.getRuntime().availableProcessors();
        int core = 1;
        //设置核心线程数
        executor.setCorePoolSize(core);
        //设置最大线程数
        executor.setMaxPoolSize(core * 2 + 1);
        //除核心线程外的线程存活时间
        executor.setKeepAliveSeconds(3);
        //如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueue
        executor.setQueueCapacity(40);
        //线程名称前缀
        executor.setThreadNamePrefix("thread-execute");
        //设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

使用方法

@Autowired
    ThreadPoolTaskExecutor myThreadPoolTaskExecutor;  // myThreadPoolTaskExecutor 为beanName

    @GetMapping("/thread")
    public Object thread() throws ExecutionException, InterruptedException {

        CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(() -> {
            for(int i = 0 ; i < 100000 ; i++){
                System.out.println("a-"+i);
            }
        }, myThreadPoolTaskExecutor);

        CompletableFuture<Void> completableFuture2 = CompletableFuture.runAsync(() -> {
            for(int i = 0 ; i < 100000 ; i++){
                System.out.println("w-"+i);
            }
        }, myThreadPoolTaskExecutor);

        // 等待两个线程执行完
        CompletableFuture.allOf(completableFuture1, completableFuture2).get();
        return "success";
    }

标签:Springboot,自定义,项目,int,CompletableFuture,executor,线程,ThreadPoolTaskExecutor
From: https://blog.51cto.com/u_14671216/6397683

相关文章

  • spring boot 项目打包到maven仓库供其它模块使用
     在对springboot项目进行打包发布的时候发现其它springboot项目服务真正引用使用该springboot包中的类 需对打包插件做如下修改:<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</arti......
  • Springboot整合EasyPOI操作Excel文件
    配合官网阅读本文源码POI官网文档效果图:本文只做一个案列的操作:pom依赖:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--EasyPoi导入导......
  • springboot整合shiro实现认证授权源码
    shiro-admin介绍springboot整合shiro实现前后端分离架构(swagger文档协调前端开发)源码地址:https://gitee.com/liujinxin_ark/shiro-admin软件架构架构说明springboot+shiro+mysql+swagger使用说明运行项目后访问http://localhost:8080/doc.html即可进入swagger接口文档界......
  • 【CV项目法规】DMS的法规政策分析
    前言 中国国家标准中国国家标准GB/T41797-2022《驾驶员注意力监测系统性能要求及试验方法》已于2022-10-14发布,并将于 2023-05-01 正式实施。国家标准|GB/T41797-2022 欧盟法规标准 欧盟法规EU2021/1341《驾驶员睡意和注意力警告系统的技术要求》于2021-04-......
  • 如何正确在多线程环境下更新UI_使用Platform的runLater方法
    如何正确在多线程环境下更新UI_使用Platform的runLater方法许多UI控件都提供了各种修改方法,比如我们可以修改Label上面的文本,进度条ProgressBar的进度。但我们必须保证修改UI的线程是JavaFX的UI线程,如果不是则会出现异常。那么我们如何在另一个线程中修改JavaFX的UI呢?......
  • Java多线程三(线程池执行完后再执行主线程)CountDownLatch
      我们在开发多线程的时候,有两种情况一种是我们处理好后,不用管结果。比如我需要查询某些数据然后存在数据库里。还有一种就是查询好数据(通过线程池),然后导出数据。这个就比较麻烦。因为我们要将数据通过多线程处理后,返回一个统一的结果。(由于多线程是在不同的时候执行数据),假如执......
  • springBoot+下载
    在springBoot我们上次文件和其他相比,就简单不少,现在我们在SpringBoot的基本框架基础上添加上传图片。一:没有新的jar包,但是在原有的jar包中必须需要有如下jar包。<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId......
  • SpringBoot中定时任务多线程任务
    SpringBoot使用Spring自带的Schedule来实现定时任务变得非常简单和方便。在这里个大家分享下。开启缓存注解@SpringBootApplication@EnableScheduling//开启定时任务publicclassApplication{publicstaticvoidmain(String[]args){SpringApplicat......
  • 项目汇报的正确打开方式
    前几天接了个私活儿,帮一家ToB企业为甲方的一个技术方案做在线支持和咨询答疑,其实就是根据甲方的需求,优化方案,然后做汇报,最终目的是为了签合同,达成交易合作。在分析甲方需求和优化方案过程中,和这家ToB企业的技术同学交流了很多,颇多感触。这篇文章,我想聊聊在日常工作中,关于汇报......
  • 前端项目中,一些好的写法
    请求consthandldeComfirmTermwork=async(params)=>{//async异步函数标识try{//捕获错误信息const{id,sid,label}=params//解构赋值constres=awaitcomfirmTermwork({id,sid,label})//发送请求if(res.code===0){......