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、编写测试代码Service方法
代码:

package com.itzhimei.itzhimei.executor;

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

@Service
public class ExecutorServiceImpl {

    @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检测到会自动使用线程池中的线程进行处理。

3、测试入口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";
    }
}

4、输出,使用接口调用地址测试:http://localhost:8080/executor/testAsync

test start:task-14
test start:task-17
test start:task-18
test start:task-19
test end:task-19
test end:task-14
test start:task-19
test end:task-17
test end:task-18
test end:task-19

我们从结果可以看到有5个线程在并发执行。

5、从断点中的代码看,使用的默认线程池是:ThreadPoolExecutor

java.lang.Thread.State: RUNNABLE
	  at com.itzhimei.itzhimei.executor.ExecutorServiceImpl.test(ExecutorServiceImpl.java:11)
	  at com.itzhimei.itzhimei.executor.ExecutorServiceImpl$$FastClassBySpringCGLIB$$623ee094.invoke(<generated>:-1)
	  at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
	  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
	  at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
	  at org.springframework.aop.interceptor.AsyncExecutionInterceptor$$Lambda$594.214106563.call(Unknown Source:-1)
	  at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	  at java.util.concurrent.FutureTask.run(FutureTask.java:-1)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	  at java.lang.Thread.run(Thread.java:748)