spring的异步实现:@Async

1 通过注解@Async实现异步处理

  在项目的启动类中加入注解@EnableAsync

  在需要实现异步的方法上面加上注解@Async

  以外露接口的形式,在controller层调用,就可以实现异步效果,代码如下

controller层代码:

@RestController
public class AsyncController {

    private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);

    @Autowired
    private IAsyncService asyncService;

    /**
     * 测试spring的异步调用顺序
     *
     * @return
     */
    @GetMapping("/async")
    public String asyncTest() {
        logger.info("************ 执行第一步 ************");
        asyncService.sync();
        asyncService.springAsync();
        logger.info("************ 执行第二步 ************");
        return "success";
    }

}

  service层代码:

@Service
public class AsyncServiceImpl implements IAsyncService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);

    /**
     * spring的异步调用
     */
    @Async
    @Override
    public void springAsync() {
        logger.info("************ 执行异步start ************");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("************ 执行异步end ************");
    }

    /**
     * 同步方法
     *
     * @return 执行结果
     */
    @Override
    public String sync() {
        logger.info("************ 执同步方法 start ************");
        logger.info("************ 执同步方法 end ************");
        return "success";
    }

  执行结果:从结果来看,程序先执行完controller层的代码,返回结果,然后才进行带有@Async的代码。实现了我们预期的效果

21:25:35.824 [http-nio-8815-exec-1] INFO  c.s.c.c.AsyncController - [asyncTest,28] - ************ 执行第一步 ************
21:25:35.824 [http-nio-8815-exec-1] INFO  c.s.c.s.i.AsyncServiceImpl - [sync,39] - ************ 执同步方法 start ************
21:25:35.824 [http-nio-8815-exec-1] INFO  c.s.c.s.i.AsyncServiceImpl - [sync,40] - ************ 执同步方法 end ************
21:25:35.827 [http-nio-8815-exec-1] INFO  c.s.c.c.AsyncController - [asyncTest,31] - ************ 执行第二步 ************
21:25:35.827 [task-1] INFO  c.s.c.s.i.AsyncServiceImpl - [springAsync,23] - ************ 执行异步start ************
21:25:38.829 [task-1] INFO  c.s.c.s.i.AsyncServiceImpl - [springAsync,29] - ************ 执行异步end ************

2 直接在service层的同一个java文件中调用带有@Async注解的方法,不能实现异步效果。

controller层代码:

@RestController
public class AsyncController {

    private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);

    @Autowired
    private IAsyncService asyncService;

    /**
     * 测试spring的异步调用顺序
     *
     * @return
     */
    @GetMapping("/async")
    public String asyncTest() {
        logger.info("************ 执行第一步 ************");
        asyncService.sync();
        logger.info("************ 执行第二步 ************");
        return "success";
    }

}

service层代码:

@Service
public class AsyncServiceImpl implements IAsyncService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);

    /**
     * spring的异步调用
     */
    @Async
    @Override
    public void springAsync() {
        logger.info("************ 执行异步start ************");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("************ 执行异步end ************");
    }

    /**
     * 同步方法
     *
     * @return 执行结果
     */
    @Override
    public String sync() {
        logger.info("************ 执同步方法 start ************");
        springAsync();
        logger.info("************ 执同步方法 end ************");
        return "success";
    }
}

  执行结果:从结果来看,异步方法执行结束后才结束了一次请求,失去了异步的效果

21:05:15.397 [http-nio-8815-exec-1] INFO  c.s.c.c.AsyncController - [asyncTest,28] - ************ 执行第一步 ************
21:05:15.463 [http-nio-8815-exec-1] INFO  c.s.c.s.i.AsyncServiceImpl - [sync,39] - ************ 执同步方法 start ************
21:05:15.463 [http-nio-8815-exec-1] INFO  c.s.c.s.i.AsyncServiceImpl - [springAsync,23] - ************ 执行异步start ************
21:05:18.464 [http-nio-8815-exec-1] INFO  c.s.c.s.i.AsyncServiceImpl - [springAsync,29] - ************ 执行异步end ************
21:05:18.464 [http-nio-8815-exec-1] INFO  c.s.c.s.i.AsyncServiceImpl - [sync,41] - ************ 执同步方法 end ************
21:05:18.464 [http-nio-8815-exec-1] INFO  c.s.c.c.AsyncController - [asyncTest,30] - ************ 执行第二步 ************

  

* 补充:何为同步异步?

  同步:就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。

  异步:则只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。(在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。)

 

总结:同spring的事务类似。spring的事务是通过代理实现的,如果需要让事务生效,那么必须要走代理才可以。除了上述的方案之外,还可以进行将AsyncServiceImpl 自己注入自己,这样就也可以生效。

posted @ 2021-03-01 15:33  zhangpba  阅读(248)  评论(0编辑  收藏  举报