zoukankan      html  css  js  c++  java
  • SpringBoot 自定义线程池处理异步任务

    1. 为什么要异步

    当我们开发中涉及短信发送,邮件发送等耗时请求时可以通过执行异步操作,从而加快请求响应,使用户体验更友好

    2. 具体操作

    创建springboot项目引入weblombok
    完整的pom.xml如下

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>thread-pool-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>thread-pool-demo</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.10</version>
                <scope>provided</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    2.1 配置application.yml

    #线程池配置参数
    task:
      pool:
        corePoolSize: 5 #设置核心线程数
        maxPoolSize: 20  #设置最大线程数
        keepAliveSeconds: 300 #设置线程活跃时间(秒)
        queueCapacity: 50 #设置队列容量
        threadNamePrefix: # 线程名称前缀
    

    2.2 编写线程池配置类

    @ConfigurationProperties(prefix = "task.pool")
    @Data
    public class TaskThreadPoolConfig {
        private int corePoolSize;           // 核心线程数(默认线程数)
        private int maxPoolSize;              // 最大线程数
        private int keepAliveTime;         // 允许线程空闲时间(单位:默认为秒)
        private int queueCapacity;        // 缓冲队列数
        private String threadNamePrefix; // 线程池名前缀
    }
    

    2.3 在启动类上开启线程异步支持

    @SpringBootApplication
    @EnableAsync        //开启线程异步支持
    @EnableConfigurationProperties({TaskThreadPoolConfig.class}) // 引入自定义线程池配置
    public class ThreadPoolDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ThreadPoolDemoApplication.class, args);
        }
    
    }
    

    2.4 创建自定义线程池

    @Configuration
    public class MyThreadPoolTaskExecutor {
        @Autowired
        private TaskThreadPoolConfig config;
    
        /**
         * 默认异步线程池
         *
         * @return
         */
        @Bean
        public ThreadPoolTaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
            pool.setThreadNamePrefix(config.getThreadNamePrefix());
            pool.setCorePoolSize(config.getCorePoolSize());
            pool.setMaxPoolSize(config.getMaxPoolSize());
            pool.setKeepAliveSeconds(config.getKeepAliveTime());
            pool.setQueueCapacity(config.getQueueCapacity());
            // 直接在execute方法的调用线程中运行
            pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 等待所有任务结束后再关闭线程池
            pool.setWaitForTasksToCompleteOnShutdown(true);
            // 初始化
            pool.initialize();
            return pool;
        }
    
    }
    

    2.5 编写测试ServiceController

    @Service
    public class TaskService {
        @Async
        public void doTaskA() throws InterruptedException {
            System.out.println("TaskA thread name->" + Thread.currentThread().getName() + "start");
            Long startTime = System.currentTimeMillis();
            TimeUnit.SECONDS.sleep(3);
            Long endTime = System.currentTimeMillis();
            System.out.println("TaskA thread name->" + Thread.currentThread().getName() + "finish");
            System.out.println("TaskA 耗时:" + (endTime - startTime));
        }
    
        @Async
        public void doTaskB() throws InterruptedException {
            System.out.println("TaskB thread name->" + Thread.currentThread().getName() + "start");
            Long startTime = System.currentTimeMillis();
            TimeUnit.SECONDS.sleep(3);
            Long endTime = System.currentTimeMillis();
            System.out.println("TaskB thread name->" + Thread.currentThread().getName() + "finish");
            System.out.println("TaskB耗时:" + (endTime - startTime));
        }
    }
    

    @RestController
    public class HelloController {
        @Autowired
        private TaskService taskService;
    
        @GetMapping("/async")
        public String testAsync() throws Exception {
            System.out.println("主线程 name -->" + Thread.currentThread().getName() + "start");
            Long startTime = System.currentTimeMillis();
            taskService.doTaskA();
            taskService.doTaskB();
            Long endTime = System.currentTimeMillis();
            System.out.println("主线程 name -->" + Thread.currentThread().getName() + "finish");
            System.out.println("主线程" + Thread.currentThread().getName() + "耗时:" + (endTime - startTime));
            return "Hello World";
        }
    }
    

    测试结果

    代码

    微云下载

    参考

    SpringBoot 自定义线程池
    SpringBoot自定义线程池处理异步任务

  • 相关阅读:
    pyqt5开发之俄罗斯方块
    Tkenter之API测试系统界面设计
    Python的标准GUI:Tkinter的组件
    Python单元测试框架——unittest
    【Android】自定义ListView的Adapter报空指针异常解决方法
    5、使用Libgdx设计一个简单的游戏------雨滴
    4.6、Libgdx线程介绍
    4.5、Libgdx运行日志管理
    4.4、Libgdx使用方法查询运行环境相关属性
    4.3、Libgdx启动类和配置
  • 原文地址:https://www.cnblogs.com/ifme/p/12800092.html
Copyright © 2011-2022 走看看