这里介绍两种 通过异步获取返回值的两种操作,这里做个小记。
1、定义示范的接口
public interface SycService {
JsonVO testSyc();
JsonVO testSyc2();
}
2、定义实现的实现类
@Service
public class SycServiceImpl implements SycService {
private static Logger logger = LoggerFactory.getLogger(SycServiceImpl.class);
/**
* 通过线程池提交 callable 实现异步
* @return
*/
@Override
public JsonVO testSyc() {
logger.error("----------通过线程池提交 callable 实现异步");
ExecutorService exceutor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
List<Future<String>> list = new ArrayList<>(5);
for (int i = 0; i < 5; i++) {
Future<String> future = exceutor.submit(new ThreadPoolTask(i + "test"));
list.add(future);
}
List<String> resultLst = new ArrayList<>();
for (Future<String> future : list) {
try {
String str = future.get(10,TimeUnit.SECONDS);
resultLst.add(str);
} catch (Exception e) {
logger.error("test Syc has error:{}", e);
}
}
exceutor.shutdown();
System.out.println("注解线程池submit获取:" + resultLst);
return new JsonVO(200,"success",resultLst);
}
/**
* 定义内部类 用于 线程池提交callable
*/
class ThreadPoolTask implements Callable<String>{
private String param;
public ThreadPoolTask(String param) {
this.param = param;
}
@Override
public String call() {
try {
System.out.println("callable 获取参数 :" + param);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return param + "--callable:123";
}
}
@Autowired
private AnnotationTask annotationTask;
/**
* 通过注解@Async 实现异步
* @return
*/
@Override
public JsonVO testSyc2() {
logger.error("----------通过注解@Async 实现异步");
List<String> resultLst = new ArrayList<>();
try {
CountDownLatch countDownLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
annotationTask.testAnnotation(i + "test",resultLst, countDownLatch);
}
countDownLatch.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
logger.error("test Syc2 has error:{}", e);
}
System.out.println("注解@Async获取:"+resultLst);
return new JsonVO(200,"success",resultLst);
}
}
3、定义 @Async注解 方式 需要的异步类,这里需要注意的是这里的异步是通过@Async的方式,如果请求太多,会一直创建线程。如果需要控制线程,可以对这个异步任务定义线程池的方式。
如果需要通过线程池对请求数进行限制可以参考:
https://blog.csdn.net/fajing_feiyue/article/details/101037662
@EnableAsync
@Component
public class AnnotationTask {
@Async
public void testAnnotation(String str, List<String> resultLst, CountDownLatch countDownLatch) {
try {
System.out.println("annotation 获取参数 :" + str);
TimeUnit.SECONDS.sleep(1);
resultLst.add(str + "--annotation:123");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
}
}
}
4、测试
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
private SycService sycService;
@Test
public void TestSyc(){
System.out.println("testSyc time start:"+formatter.format(LocalDateTime.now()));
JsonVO jsonVO = sycService.testSyc();
System.out.println("--------------testSyc----------- time:"+formatter.format(LocalDateTime.now()));
System.out.println(jsonVO);
JsonVO jsonVO2 = sycService.testSyc2();
System.out.println("--------------testSyc2-----------time:"+formatter.format(LocalDateTime.now()));
System.out.println(jsonVO2);
}
测试结果:
[2020-02-22 15:53:10:539] | [ERROR] [main] [com.yin.dynamic_elasticjob.service.impl.SycServiceImpl] [29] -| ----------通过线程池提交 callable 实现异步
callable 获取参数 :2test
callable 获取参数 :1test
callable 获取参数 :3test
callable 获取参数 :0test
callable 获取参数 :4test
注解线程池submit获取:[0test--callable:123, 1test--callable:123, 2test--callable:123, 3test--callable:123, 4test--callable:123]
--------------testSyc----------- time:2020-02-22 15:53:11
JsonVO(statusCode=200, errorMessage=success, data=[0test--callable:123, 1test--callable:123, 2test--callable:123, 3test--callable:123, 4test--callable:123])
[2020-02-22 15:53:11:559] | [ERROR] [main] [com.yin.dynamic_elasticjob.service.impl.SycServiceImpl] [75] -| ----------通过注解@Async实现异步
annotation 获取参数 :0test
annotation 获取参数 :3test
annotation 获取参数 :4test
annotation 获取参数 :1test
annotation 获取参数 :2test
注解@Async获取:[0test--annotation:123, 4test--annotation:123, 1test--annotation:123, 3test--annotation:123, 2test--annotation:123]
--------------testSyc2-----------time:2020-02-22 15:53:12
JsonVO(statusCode=200, errorMessage=success, data=[0test--annotation:123, 4test--annotation:123, 1test--annotation:123, 3test--annotation:123, 2test--annotation:123])
可以看到两种方式都获取到想要的结果,在这次示范两次获取数据都控制获取到数据的返回时间。线程池提交 callable 的这种方式 每个请求都有频繁创建线程池,@Async 注解的方式,一直是使用的一个线程池,对性能会相对好一点。两种方式 都没有对示范创建的线程限制,可能创建的线程使用飙升,对cpu负载过高。如果有必要刻意通过配置总的线程池对其限制,防止无限创建线程。