springboot中开启@Async异步支持:
其实,@Async的异步调用从spring3.x之后就开始支持了,springboot中当然也可以使用。
1、配置AsyncConfig配置类
package com.tingcream.springmybatis.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @EnableAsync//开启Async异步调用支持 @Configuration public class AsyncConfig { /** * 自定义异步线程的执行器 ,springboot中默认寻找的执行器名称为"taskExecutor" */ @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 设置核心线程数 executor.setCorePoolSize(10); // 设置最大线程数 executor.setMaxPoolSize(20); // 设置队列容量 executor.setQueueCapacity(20); // 设置线程活跃时间(秒) executor.setKeepAliveSeconds(60); // 设置线程名称前缀 executor.setThreadNamePrefix("async-task-thread-"); return executor; } }
2、AsyncController(测试controller层)
package com.tingcream.springmybatis.async.controller; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.tingcream.springmybatis.async.service.AsyncService; import com.tingcream.springmybatis.common.RetMsg; /** * 异步调用测试 controller层 * @author jelly */ @RestController @RequestMapping("/async") public class AsyncController { @Autowired private AsyncService asyncService ; @RequestMapping("/test1") public RetMsg<?> test1(String name) { long t1=System.currentTimeMillis(); Future<String> n = asyncService.getName(name); Future<Integer> age = asyncService.getAge(); Map<String,Object> map =new HashMap<String,Object>(); try { map.put("name", n.get());// 调用Feture<V>对象的get方法会产生阻塞,直到有结果返回 map.put("age", age.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } long t2=System.currentTimeMillis(); long sec= (t2-t1)/1000; System.out.println("耗时:"+sec+"秒"); map.put("ts",sec+"秒"); //4秒 return RetMsg.success(map); } }3、AsyncService(测试service层)
package com.tingcream.springmybatis.async.service; import java.util.concurrent.Future; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; /** * 异步调用测试 service层 * @author jelly * */ @Service public class AsyncService { @Async public Future<String> getName(String name) { try { System.out.println("线程名:"+Thread.currentThread().getName()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } // return AsyncResult.forValue("hi:"+name) ; return new AsyncResult<>("hi:"+name); } @Async public Future<Integer> getAge() { try { System.out.println("线程名:"+Thread.currentThread().getName()); Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } return new AsyncResult<>(22); } }
浏览器请求: http://localhost:8081/async/test1?name=zhangsan
控制台输出:
4、附:关于线程池的执行及任务代理
@Async注解中还可以指定value的值,可通过bean名称来指定调用的线程池, springboot默认会使用名称为"taskExecutor"的线程池,如果没有找到,才会使用其他类型为TaskExecutor或其子类的线程池。例如:@Async("MyExecutor") 就可以改为使用其他的线程池对象去执行异步任务。
spring中的线程执行器
Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象。 Spring的TaskExecutor和java.util.concurrent.Executor接口时一样的,这个接口只有一个方法execute(Runnable task)。 Spring已经内置了许多TaskExecutor的实现,没有必要自己去实现: 1、SimpleAsyncTaskExecutor 这种实现不会重用任何线程,每次调用都会创建一个新的线程。 2、SyncTaskExecutor 这种实现不会异步的执行 3、ConcurrentTaskExecutor 这种实现是java.util.concurrent.Executor的一个adapter。 4、SimpleThreadPoolTaskExecutor 这种实现实际上是Quartz的SimpleThreadPool的一个子类,它监听Spring的声明周期回调。 5、ThreadPoolTaskExecutor 这是最常用最通用的一种实现。它包含了java.util.concurrent.ThreadPoolExecutor的属性,并且用TaskExecutor进行包装。
spring中async代理对象
Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1