spring的异步实现:@Async

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

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

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

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

controller层代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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层代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@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的代码。实现了我们预期的效果

1
2
3
4
5
6
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层代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@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";
    }
}

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

1
2
3
4
5
6
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 @   zhangpba  阅读(252)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示