同步执行和异步线程池的方式执行和springboot中使用@Async加@EanbleAsync的方式对比。
1.同步执行:
@RestController public class TestController { @Autowired private TestService service; /**@ * 使用传统方式测试 */ @GetMapping("/test") public void test() { System.out.println("获取主线程名称:" + Thread.currentThread().getName()); service.serviceTest(); System.out.println("执行完成,向用户响应成功信息"); } }
@Service public class TestService { public void serviceTest() { // 这里执行实际的业务逻辑,在这里我们就是用一个简单的遍历来模拟 Arrays.stream(new int[]{1,2,3,4,5,6,7,8,9,10}).forEach(t -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("获取number为:" + t) ; }); } }
输出的结果为:
获取主线程名称:http-nio-8080-exec-2
获取number为:1
获取number为:2
获取number为:3
获取number为:4
获取number为:5
获取number为:6
获取number为:7
获取number为:8
获取number为:9
获取number为:10
执行完成,向用户响应成功信息
先执行方法,执行完成方法中的循环之后再返回响应信息。
2.异步线程池执行:
@RestController public class TestThreadController { @Autowired private TestThreadService threadService; /** * 使用传统方式测试 */ @GetMapping("/test") public void test() { System.out.println("获取主线程名称:" + Thread.currentThread().getName()); /** * 这里也可以采用以下方式使用,但是使用线程池的方式可以很便捷的对线程管理(提高程序的整体性能), * 也可以减少每次执行该请求时都需要创建一个线程造成的性能消耗 * new Thread(() ->{ * run方法中的业务逻辑 * }) */ /** * 定义一个线程池 * 核心线程数(corePoolSize):1 * 最大线程数(maximumPoolSize): 1 * 保持连接时间(keepAliveTime):50000 * 时间单位 (TimeUnit):TimeUnit.MILLISECONDS(毫秒) * 阻塞队列 new LinkedBlockingQueue<Runnable>() */ ThreadPoolExecutor executor = new ThreadPoolExecutor(1,5,50000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); // 执行业务逻辑方法serviceTest() executor.execute(new Runnable() { @Override public void run() { threadService.serviceTest(); } }); System.out.println("执行完成,向用户响应成功信息"); } }
TestThreadService和TestService的内容一样不在重复写。
输出结果:
获取主线程名称:http-nio-8080-exec-2
执行完成,向用户响应成功信息
获取number为:1
获取number为:2
获取number为:3
获取number为:4
获取number为:5
获取number为:6
获取number为:7
获取number为:8
获取number为:9
获取number为:10
直接返回响应信息,然后执行方法中的循环。
3.spring的注解@Async和@EableAsync:
@RestController public class TestAsyncController { @Autowired private TestAsyncService asyncService; /** * 使用传统方式测试 */ @GetMapping("/testAsync") public void test() { System.out.println("获取主线程名称:" + Thread.currentThread().getName()); asyncService.serviceTest(); System.out.println("执行完成,向用户响应成功信息"); } }
@Service @EnableAsync public class TestAsyncService { @Async public void serviceTest() { // 这里执行实际的业务逻辑,在这里我们就是用一个简单的遍历来模拟 Arrays.stream(new int[]{1,2,3,4,5,6,7,8,9,10}).forEach(t -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("获取number为:" + t) ; }); } }
输出结果:
获取主线程名称:http-nio-8080-exec-2
执行完成,向用户响应成功信息
获取number为:1
获取number为:2
获取number为:3
获取number为:4
获取number为:5
获取number为:6
获取number为:7
获取number为:8
获取number为:9
获取number为:10
同样直接返回响应信息,然后执行方法中的循环。
@Async标记方法之后表示这是个异步方法,@Async必须和@EableAsync一起使用,否者不起作用,
在使用@Async的使用也是可以自己定义线程池。
其实异步的方式也可以用消息队列来实现。