├── README.md ├── src ├── main │ ├── resources │ │ └── application.properties │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ ├── annotationTask │ │ ├── Package_Info.java │ │ ├── exceptionHandler │ │ │ └── MyAsyncConfigurer.java │ │ └── tasks │ │ │ └── MyTasks.java │ │ ├── DemoApplication.java │ │ ├── schedual │ │ ├── AsyncSchedualTask.java │ │ └── Task.java │ │ ├── controller │ │ ├── AnnotationController.java │ │ └── GetUserInfoController.java │ │ └── executor │ │ └── MyExecutor.java └── test │ └── java │ └── com │ └── example │ └── demo │ └── DemoApplicationTests.java └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | # WebAsyncTask 2 | WebAsyncTask异步任务样例工程---spring boot/spring 3 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=7000 2 | server.servlet.context-path=/demo -------------------------------------------------------------------------------- /src/main/java/com/example/demo/annotationTask/Package_Info.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.annotationTask; 2 | 3 | /** 4 | * 5 | * The class Package_Info. 6 | * 7 | * Description:该包主要演示了基于注解的Spring异步任务 8 | * 9 | * @author: huangjiawei 10 | * @since: 2018年6月15日 11 | * @version: $Revision$ $Date$ $LastChangedBy$ 12 | * 13 | */ 14 | public class Package_Info { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/example/demo/DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | @SpringBootApplication 9 | @EnableAsync 10 | @EnableScheduling 11 | public class DemoApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(DemoApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/schedual/AsyncSchedualTask.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.schedual; 2 | 3 | import org.springframework.scheduling.annotation.Async; 4 | import org.springframework.stereotype.Component; 5 | 6 | /** 7 | * 8 | * The class AsyncSchedualTask. 9 | * 10 | * Description:基于Spring定时任务的异步任务调用,也就是说测试在定时任务中调用地步方法,看看能不能异步执行 11 | * 12 | * @author: huangjiawei 13 | * @since: 2018年6月15日 14 | * @version: $Revision$ $Date$ $LastChangedBy$ 15 | * 16 | */ 17 | @Component 18 | public class AsyncSchedualTask { 19 | 20 | @Async 21 | public void async() { 22 | 23 | System.err.println(Thread.currentThread().getName() + "线程执行"); 24 | System.err.println("async"); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/schedual/Task.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.schedual; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.scheduling.annotation.Scheduled; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * 9 | * The class Task. 10 | * 11 | * Description:要有以下两个保证 12 | * 13 | * 1、异步任务类定义和定时任务定义不能在同一个类中 14 | * 2、异步任务类不能采用new的方式创建,只能从spring容器中获取 15 | * 16 | * @author: huangjiawei 17 | * @since: 2018年6月15日 18 | * @version: $Revision$ $Date$ $LastChangedBy$ 19 | * 20 | */ 21 | @Component 22 | public class Task { 23 | 24 | @Autowired 25 | private AsyncSchedualTask asyncTask; 26 | 27 | /** 28 | * 每两秒执行一次 29 | * @throws InterruptedException 30 | */ 31 | @Scheduled(cron = "0/2 * * * * ?") 32 | public void say() throws InterruptedException { 33 | System.err.println(Thread.currentThread().getName() + "线程执行"); 34 | System.err.println("say"); 35 | Thread.sleep(2000L); 36 | asyncTask.async(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/annotationTask/exceptionHandler/MyAsyncConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.annotationTask.exceptionHandler; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.Arrays; 5 | 6 | import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; 7 | import org.springframework.scheduling.annotation.AsyncConfigurer; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | public class MyAsyncConfigurer implements AsyncConfigurer { 12 | 13 | @Override 14 | public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 15 | return new handler(); 16 | } 17 | } 18 | 19 | /** 20 | * 21 | * The class handler. 22 | * 23 | * Description:异常信息捕获 24 | * 25 | * @author: huangjiawei 26 | * @since: 2018年6月15日 27 | * @version: $Revision$ $Date$ $LastChangedBy$ 28 | * 29 | */ 30 | class handler implements AsyncUncaughtExceptionHandler { 31 | 32 | @Override 33 | public void handleUncaughtException(Throwable ex, Method method, Object... params) { 34 | System.err.println("出现异常的方法名为: " + method.getName()); 35 | System.err.println("出现的参数为:" + Arrays.toString(params)); 36 | System.err.println("抛出的异常信息为: " + ex.getMessage()); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/annotationTask/tasks/MyTasks.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.annotationTask.tasks; 2 | 3 | import java.util.concurrent.Future; 4 | 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.scheduling.annotation.AsyncResult; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | public class MyTasks { 11 | 12 | /** 13 | * 正常的异步任务处理(没有返回值) 14 | * @throws InterruptedException 15 | */ 16 | @Async 17 | public void getUserInfoAnnotationWithoutReturn() throws InterruptedException { 18 | System.out.println("当前异步任务线程名为 : " + Thread.currentThread().getName()); 19 | System.err.println("这是一个没有任何返回值的异步方法!"); 20 | Thread.sleep(5 * 1000L); 21 | System.err.println("getUserInfoAnnotationWithoutReturn方法运行结束了!"); 22 | } 23 | 24 | /** 25 | * 正常的异步任务处理(有返回值) 26 | * @throws InterruptedException 27 | */ 28 | @Async 29 | public Future getUserInfoAnnotationWithString() throws InterruptedException { 30 | System.out.println("当前异步任务线程名为 : " + Thread.currentThread().getName()); 31 | System.err.println("这是一个有返回值的异步方法!"); 32 | Future futureResult = new AsyncResult("getUserInfoAnnotationWithString执行成功啦!"); 33 | Thread.sleep(5 * 1000L); 34 | System.err.println("getUserInfoAnnotationWithString方法运行结束了!"); 35 | return futureResult; 36 | } 37 | 38 | /** 39 | * 测试异常异步任务 40 | * @return 41 | */ 42 | @Async 43 | public String getUserInfoAnnotationWithException() throws InterruptedException { 44 | System.out.println("当前异步任务线程名为 : " + Thread.currentThread().getName()); 45 | System.err.println("这是一个有异常的异步方法!"); 46 | int b = 10 / 0; 47 | Thread.sleep(5 * 1000L); 48 | System.err.println("getUserInfoAnnotationWithString方法运行结束了!"); 49 | return ""; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | demo 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.2.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-devtools 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-web 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/controller/AnnotationController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import java.util.concurrent.Future; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.example.demo.annotationTask.tasks.MyTasks; 12 | 13 | /** 14 | * 15 | * The class AnnotationController. 16 | * 17 | * Description:基于注解的异步控制器 18 | * 19 | * @author: huangjiawei 20 | * @since: 2018年6月15日 21 | * @version: $Revision$ $Date$ $LastChangedBy$ 22 | * 23 | */ 24 | @RestController 25 | public class AnnotationController { 26 | 27 | @Autowired 28 | private MyTasks myTask; 29 | 30 | /** 31 | * 测试没有返回值的异步任务(注解) 32 | * @return 33 | */ 34 | @RequestMapping(value = "getUserInfoAnnotationWithoutReturn.json", method = RequestMethod.GET) 35 | public String getUserInfoAnnotationWithoutReturn() { 36 | System.err.println("当前处理线程名为 : " + Thread.currentThread().getName()); 37 | try { 38 | myTask.getUserInfoAnnotationWithoutReturn(); 39 | } catch (InterruptedException e) {} 40 | return "success"; 41 | } 42 | 43 | /** 44 | * 测试有返回值的异步任务(注解) 45 | * @return 46 | */ 47 | @RequestMapping(value = "getUserInfoAnnotationWithString.json", method = RequestMethod.GET) 48 | public String getUserInfoAnnotationWithString() { 49 | System.err.println("当前处理线程名为 : " + Thread.currentThread().getName()); 50 | Future futureResult = null; 51 | String returnResult = ""; 52 | try { 53 | futureResult = myTask.getUserInfoAnnotationWithString(); 54 | returnResult = futureResult.get(2L, TimeUnit.SECONDS); 55 | } catch (Exception e) { 56 | return "处理超时"; 57 | } 58 | return returnResult; 59 | } 60 | 61 | /** 62 | * 测试有异常的异步任务 63 | * @return 64 | * @throws InterruptedException 65 | */ 66 | @RequestMapping(value = "getUserInfoAnnotationWithException.json", method = RequestMethod.GET) 67 | public String getUserInfoAnnotationWithException() throws InterruptedException { 68 | System.err.println("当前处理线程名为 : " + Thread.currentThread().getName()); 69 | myTask.getUserInfoAnnotationWithException(); 70 | return ""; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/executor/MyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.executor; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.net.URI; 8 | import java.net.URISyntaxException; 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.Executors; 11 | 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.http.HttpMethod; 15 | import org.springframework.http.client.ClientHttpRequest; 16 | import org.springframework.http.client.ClientHttpResponse; 17 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 18 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 19 | 20 | @Configuration 21 | public class MyExecutor { 22 | 23 | @Bean 24 | public static ThreadPoolTaskExecutor getExecutor() { 25 | ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); 26 | taskExecutor.setCorePoolSize(30); 27 | taskExecutor.setMaxPoolSize(30); 28 | taskExecutor.setQueueCapacity(50); 29 | taskExecutor.setThreadNamePrefix("huang"); 30 | return taskExecutor; 31 | } 32 | 33 | public static void main(String[] args) { 34 | ExecutorService executor = Executors.newFixedThreadPool(40); 35 | for (int i = 0; i < 100; i++) { 36 | executor.execute(() -> { 37 | http(); 38 | }); 39 | } 40 | } 41 | 42 | public static void http() { 43 | try { 44 | //TODO: 准备uri 45 | URI uri = new URI("http://localhost:7000/demo/getUserInfoAnnotationWithoutReturn.json"); 46 | 47 | //TODO: new一个HTTP工厂 48 | SimpleClientHttpRequestFactory schr = new SimpleClientHttpRequestFactory(); 49 | 50 | //TODO: 创建HTTP请求 51 | ClientHttpRequest chr = schr.createRequest(uri, HttpMethod.GET); 52 | 53 | //TODO:设置body 54 | //chr.getBody().write(param.getBytes()); 55 | 56 | //TODO: 执行HTTP请求 57 | ClientHttpResponse res = chr.execute(); 58 | 59 | //TODO: 获取返回数据流 60 | InputStream is = res.getBody(); 61 | 62 | //TODO: 从流中读取数据 63 | InputStreamReader isr = new InputStreamReader(is); 64 | BufferedReader br = new BufferedReader(isr); 65 | String str = ""; 66 | while ((str = br.readLine()) != null) { 67 | System.out.println(str); 68 | } 69 | 70 | } catch (URISyntaxException e1) { 71 | // TODO Auto-generated catch block 72 | e1.printStackTrace(); 73 | } catch (IOException e) { 74 | // TODO Auto-generated catch block 75 | e.printStackTrace(); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/controller/GetUserInfoController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import org.springframework.web.context.request.async.WebAsyncTask; 9 | 10 | /** 11 | * 12 | * The class GetUserInfoController. 13 | * 14 | * Description:用户控制器 15 | * 16 | * @author: huangjiawei 17 | * @since: 2018年6月14日 18 | * @version: $Revision$ $Date$ $LastChangedBy$ 19 | * 20 | */ 21 | @RestController 22 | public class GetUserInfoController { 23 | 24 | @Autowired 25 | private ThreadPoolTaskExecutor executor; 26 | 27 | /** 28 | * 测试没有发生任何异常的异步任务 29 | * @return 30 | */ 31 | @RequestMapping(value = "getUserWithNoThing.json", method = RequestMethod.GET) 32 | public WebAsyncTask getUserWithNoThing() { 33 | System.err.println("The main Thread name is " + Thread.currentThread().getName()); 34 | 35 | // 此处模拟开启一个异步任务 36 | WebAsyncTask task1 = new WebAsyncTask(10 * 1000L, () -> { 37 | System.err.println("The first Thread name is " + Thread.currentThread().getName()); 38 | Thread.sleep(5 * 1000L); 39 | return "任务1顺利执行成功!任何异常都没有抛出!"; 40 | }); 41 | 42 | // 任务执行完成时调用该方法 43 | task1.onCompletion(() -> { 44 | System.err.println("任务1执行完成啦!"); 45 | }); 46 | 47 | System.err.println("task1继续处理其他事情!"); 48 | return task1; 49 | } 50 | 51 | /** 52 | * 测试发生任务超时的异步任务 53 | * @return 54 | */ 55 | @RequestMapping(value = "getUserWithTimeOut.json", method = RequestMethod.GET) 56 | public WebAsyncTask getUserWithTimeOut() { 57 | System.err.println("The main Thread name is " + Thread.currentThread().getName()); 58 | 59 | // 此处模拟开启一个异步任务 60 | WebAsyncTask task2 = new WebAsyncTask(10 * 1000L, () -> { 61 | System.err.println("The second Thread name is " + Thread.currentThread().getName()); 62 | Thread.sleep(20 * 1000L); 63 | return "任务2执行超时!"; 64 | }); 65 | 66 | // 任务超时调用该方法 67 | task2.onTimeout(() -> { 68 | System.err.println("====================================" + Thread.currentThread().getName() 69 | + "=============================="); 70 | return "任务2发生超时啦!"; 71 | }); 72 | 73 | // 任务执行完成时调用该方法 74 | task2.onCompletion(() -> { 75 | System.err.println("任务2执行完成啦!"); 76 | }); 77 | 78 | System.err.println("task2继续处理其他事情!"); 79 | return task2; 80 | } 81 | 82 | /** 83 | * 测试发生error的异步任务 84 | * @return 85 | */ 86 | @RequestMapping(value = "getUserWithError.json", method = RequestMethod.GET) 87 | public WebAsyncTask getUserWithError() { 88 | System.err.println("The main Thread name is " + Thread.currentThread().getName()); 89 | 90 | // 此处模拟开启一个异步任务 91 | WebAsyncTask task3 = new WebAsyncTask(10 * 1000L, () -> { 92 | System.err.println("The second Thread name is " + Thread.currentThread().getName()); 93 | int num = 9 / 0; 94 | System.err.println(num); 95 | return ""; 96 | }); 97 | 98 | // 发生异常时调用该方法 99 | task3.onError(() -> { 100 | System.err.println("====================================" + Thread.currentThread().getName() 101 | + "=============================="); 102 | System.err.println("任务3发生error啦!"); 103 | return ""; 104 | }); 105 | // 任务执行完成时调用该方法 106 | task3.onCompletion(() -> { 107 | System.err.println("任务3执行完成啦!"); 108 | }); 109 | 110 | System.err.println("task3继续处理其他事情!"); 111 | return task3; 112 | } 113 | 114 | /** 115 | * 测试线程池 116 | * @return 117 | */ 118 | @RequestMapping(value = "getUserWithExecutor.json", method = RequestMethod.GET) 119 | public WebAsyncTask getUserWithExecutor() { 120 | System.err.println("The main Thread name is " + Thread.currentThread().getName()); 121 | 122 | // 此处模拟开启一个异步任务 123 | WebAsyncTask task1 = new WebAsyncTask(10 * 1000L, executor, () -> { 124 | System.err.println("The first Thread name is " + Thread.currentThread().getName()); 125 | Thread.sleep(5000L); 126 | return "任务4顺利执行成功!任何异常都没有抛出!"; 127 | }); 128 | 129 | // 任务执行完成时调用该方法 130 | task1.onCompletion(() -> { 131 | System.err.println("任务4执行完成啦!"); 132 | }); 133 | 134 | System.err.println("task4继续处理其他事情!"); 135 | return task1; 136 | } 137 | } 138 | --------------------------------------------------------------------------------