异步获取返回值(@Async注解 和 线程池提交 callable 两种方式)

这里介绍两种 通过异步获取返回值的两种操作,这里做个小记。

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负载过高。如果有必要刻意通过配置总的线程池对其限制,防止无限创建线程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章