一.springboot开线程执行异步任务
1.Spring通过任务执行器TaskExecutor,来实现多线程和并发编程,使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor;
2.异步需要在配置类上面加 @EnableAsync 来开启对异步任务的支持在需要异步执行的方法上面加@Async 来声明这个方法是一个需要异步执行的方法;
3. 让配置类实现AsyncConfigurer接口,并重写getAsyncExecutor方法,并返回一个ThreasPoolTaskExecutor,就可以获取一个基于线程池的TaskExecutor;
4. @Async 用在方法上,表示这个方法是一个异步的方法,如果用在类上面,表明这个类中的所有方法都是异步的方法。
(1).配置类
1 package com.yunzhangfang.springboot1.config;
2
3 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
4 import org.springframework.context.annotation.ComponentScan;
5 import org.springframework.context.annotation.Configuration;
6 import org.springframework.scheduling.annotation.AsyncConfigurer;
7 import org.springframework.scheduling.annotation.EnableAsync;
8 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
9
10 import java.util.concurrent.Executor;
11
12 @Configuration
13 @ComponentScan("com.yunzhangfang.springboot1.service")
14 @EnableAsync
15 public class ThreadConfig implements AsyncConfigurer {
16
17 // ThredPoolTaskExcutor的处理流程
18 // 当池子大小小于corePoolSize,就新建线程,并处理请求
19 // 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
20 // 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
21 // 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁
22 @Override
23 public Executor getAsyncExecutor() {
24 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
25 executor.setCorePoolSize(5);
26 executor.setMaxPoolSize(15);
27 executor.setQueueCapacity(25);
28 executor.initialize();
29 return executor;
30 }
31
32 @Override
33 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
34 return null;
35 }
36
37 }
(2).异步任务
1 package com.yunzhangfang.springboot1.service;
2
3 import org.springframework.scheduling.annotation.Async;
4 import org.springframework.scheduling.annotation.AsyncResult;
5 import org.springframework.stereotype.Service;
6
7 import java.util.concurrent.Future;
8
9 @Service
10 public class TaskService {
11
12 @Async
13 /**
14 * 表明是异步调用
15 * 没有返回值
16 */
17 public void excutVoidTask(int i) {
18 System.out.println("异步执行任务第[" + i + "] 个");
19 }
20
21 /**
22 * 有返回值
23 * 异常调用
24 *
25 * @param i
26 * @return
27 * @throws InterruptedException
28 */
29 @Async
30 public Future<String> excuteValueTask(int i) throws InterruptedException {
31 Thread.sleep(1000);
32 Future<String> future = new AsyncResult<String>("success is " + i);
33 System.out.println("异步执行任务第[" + i + "] 个");
34 return future;
35 }
36
37 }
(3).测试异步任务
1 package com.yunzhangfang.springboot1;
2
3 import com.yunzhangfang.springboot1.service.TaskService;
4 import org.junit.Test;
5 import org.junit.runner.RunWith;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.boot.test.context.SpringBootTest;
8 import org.springframework.core.task.TaskRejectedException;
9 import org.springframework.test.context.junit4.SpringRunner;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
15
16 @RunWith(SpringRunner.class)
17 @SpringBootTest
18 public class Springboot1ApplicationTests {
19
20 @Autowired
21 private TaskService service;
22
23 @Test
24 public void contextLoads() {
25 }
26
27 /**
28 * 没有返回值测试
29 */
30 @Test
31 public void testVoid() {
32 for (int i = 0; i < 20; i++) {
33 service.excutVoidTask(i);
34 }
35 System.out.println("========主线程执行完毕=========");
36 }
37
38 @Test
39 public void testReturn() throws InterruptedException, ExecutionException {
40 List<Future<String>> lstFuture = new ArrayList<>();// 存放所有的线程,用于获取结果
41 for (int i = 0; i < 100; i++) {
42 while (true) {
43 try {
44 // 线程池超过最大线程数时,会抛出TaskRejectedException,则等待1s,直到不抛出异常为止
45 Future<String> stringFuture = service.excuteValueTask(i);
46 lstFuture.add(stringFuture);
47 break;
48 } catch (TaskRejectedException e) {
49 System.out.println("线程池满,等待1S。");
50 Thread.sleep(1000);
51 }
52 }
53 }
54
55 // 获取值.get是阻塞式,等待当前线程完成才返回值
56 for (Future<String> future : lstFuture) {
57 System.out.println(future.get());
58 }
59
60 System.out.println("========主线程执行完毕=========");
61 }
62
63 }
有错误,希望指出,共同进步,天天向上