Spring | 基于Spring实现线程池

Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。而实际开发中任务一般是非阻碍的,即异步的,所以我们要在配置类中通过@EnableAsync开启对异步任务的支持,并通过在实际执行的Bean的方法中使用@Async注解声明其是一个异步任务。

一、Maven

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </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>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

二、配置类

package com.example.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 配置类实现AsyncConfigurer接口,并重写getAsyncExecutor方法,并返回一个ThreadPoolTaskExecutor
 */
@Configuration
@ComponentScan("com.example") // 定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中
@EnableAsync // 利用@EnableAsync注解开启异步任务支持
public class CustomMultiThreadingConfig implements AsyncConfigurer {
    
    
    @Override
    public Executor getAsyncExecutor() {
    
    
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5); // 核心线程数
        taskExecutor.setMaxPoolSize(10); // 最大线程数
        taskExecutor.setQueueCapacity(25); ///配置队列大小
        taskExecutor.setThreadNamePrefix("async-service-"); // 配置线程池前缀
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); // 配置拒绝策略
        taskExecutor.initialize(); // 数据初始化
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    
    
        return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
    }
}

捕获线程异常信息

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Slf4j
@Component
public class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    
    
    @Override
    public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
    
    
        log.info("------------->>>捕获线程异常信息");
        log.info("Exception message - " + throwable.getMessage());
        log.info("Method name - " + method.getName());
        for (Object param : objects) {
    
    
            log.info("Parameter value - " + param);
        }
    }
}

ThredPoolTaskExcutor的处理流程

当池子大小小于corePoolSize,就新建线程,并处理请求
当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁

三、创建线程任务

package com.example.service.impl;

import com.example.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class TestServiceImpl implements TestService {
    
    
    private Logger logger = LoggerFactory.getLogger(TestServiceImpl.class);

    /**
     * 通过@Async注解表明该方法是一个异步方法,
     * 如果注解在类级别上,则表明该类所有的方法都是异步方法,而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     */
    @Async
    public void executeAsyncTask1(Integer i) {
    
    
        logger.info("CustomMultiThreadingService ==> executeAysncTask1 method: 执行异步任务{} ", i);
    }

    @Async
    public void executeAsyncTask2(Integer i) {
    
    
        logger.info("CustomMultiThreadingService ==> executeAsyncTask2 method: 执行异步任务{} ", i);
    }
}

四、测试

package com.example.controller;

import com.example.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(value = "/testController")
public class TestController {
    
    
    @Autowired
    private TestService testService;

    @ResponseBody
    @RequestMapping(value = "/doTask")
    public String doTask() {
    
    
        for (int i = 0; i < 10; i++) {
    
    
            testService.executeAsyncTask1(i);
            testService.executeAsyncTask2(i);
        }
        return "success";
    }
}

五、效果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/y1534414425/article/details/108584217