在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)