Spring | Implementation of thread pool based on Spring

Spring (TaskExecutor)implements multithreading and concurrent programming through task executors . Use ThreadPoolTaskExecutorcan be realized based on a thread pool TaskExecutor. In actual development, tasks are generally non-blocking, that is, asynchronous, so we have to @EnableAsyncenable support for asynchronous tasks in the configuration class , and @Asyncdeclare that it is an asynchronous task by using annotations in the method of the actual executed Bean .

One, 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>

Two, configuration class

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();
    }
}

Capture thread exception information

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 processing flow

When the pool size is less than corePoolSize, on the new thread, and processes the request
when the pool size is equal corePoolSize, put into the request workQueue, the idle thread pool workQueue go fetch processing task and
when workQueuethe time does not fit the task into the pool on the new thread, and the processing request, if the pool size to hold maximumPoolSize, to use RejectedExecutionHandlerto do the processing refuse
when the pond is greater than the number of threads corePoolSize, the thread waits for the extra keepAliveTimetime, if no request may be processed to self-destruct

Three, create thread task

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);
    }
}

Four, test

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";
    }
}

Five, effect

Insert picture description here

Guess you like

Origin blog.csdn.net/y1534414425/article/details/108584217