SpringBoot使用自定义线程池并发编程

在SpringBoot或Spring中使用并发编程变得很简单了,如果开发者不定义线程池,SpringBoot或Spring会使用默认定义的线程池,如果用户自定义了线程池,则使用用户自定义的线程池。

我们来看如何在SpringBoot中使用自定义线程池进行并发编程。

1、SpringBoot启动类上添加异步@EnableAsync
代码:

@EnableAsync
@SpringBootApplication
public class MyspringbootApplication {

	public static void main(String[] args) {
		SpringApplication.run(MyspringbootApplication.class, args);
	}

}

2、自定义线程池
代码:

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

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class TaskExecutorConfig {

	//@Bean("task-executor")  //如果要自定义多个线程池,则指定自定义线程池的名称,方便业务代码指定使用的线程池
    @Bean
    public TaskExecutor taskExecutor(){
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(10);
        taskExecutor.setMaxPoolSize(50);
        taskExecutor.setQueueCapacity(100);
        taskExecutor.setKeepAliveSeconds(300);
        taskExecutor.setThreadNamePrefix("自定义-TaskExecutor");
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return taskExecutor;
    }
}

3、编写测试代码Service方法
代码:

package com.itzhimei.itzhimei.executor;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class ExecutorServiceImpl {

	//@Async("task-executor") //括号中指定的就是要引用的线程池的名称
    @Async
    public void test() throws InterruptedException {
        System.out.println("test start:"+Thread.currentThread().getName());
        Thread.sleep(1000);
        System.out.println("test end:"+Thread.currentThread().getName());
    }
}

这里的重点是test()方法上的注解:@Async,这个注解的方法,spring检测到会自动使用线程池中的线程进行处理。

4、测试入口Controller
代码:

package com.itzhimei.itzhimei.executor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExecutorController {

    @Autowired
    private ExecutorServiceImpl executorService;

    @RequestMapping(value = "/executor/testAsync", method = RequestMethod.GET, produces = "application/json")
    public String testAsync() throws InterruptedException {
        executorService.test();
        executorService.test();
        executorService.test();
        executorService.test();
        executorService.test();

        Thread.sleep(2000);
        return "testAsync";
    }
}

5、输出,测试地址接口:http://localhost:8080/executor/testAsync

test start:自定义-TaskExecutor5
test start:自定义-TaskExecutor4
test start:自定义-TaskExecutor1
test start:自定义-TaskExecutor2
test start:自定义-TaskExecutor3
test end:自定义-TaskExecutor3
test end:自定义-TaskExecutor2
test end:自定义-TaskExecutor5
test end:自定义-TaskExecutor4
test end:自定义-TaskExecutor1

我们从结果可以看到有5个线程在并发执行,线程名称也是我们自定义线程池定义的前缀名称:“自定义-TaskExecutor”。