這裏介紹兩種 通過異步獲取返回值的兩種操作,這裏做個小記。
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負載過高。如果有必要刻意通過配置總的線程池對其限制,防止無限創建線程。