@Async 异步调用

本文介绍了Spring Boot中@Async注解实现异步调用的原理,强调了当异步方法被同一类内部方法调用时可能会失效的原因,即未通过动态生成的代理类。启动类上的配置是关键,理解其背后的代理机制对于正确使用@Async至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.example.demo.controller;

import com.example.demo.service.AsyncService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@RequestMapping("/async")
public class AsyncController {

    @Resource
    private AsyncService asyncService;

    /**
     * 测试eureka
     */
    @Resource
    RestTemplate restTemplate;

    @RequestMapping("/test1")
    public void fun01(){
//        服务id
        String serverId  =  "TEST";

//        通过服务id 调用
        ResponseEntity<Map> responseEntity = restTemplate.getForEntity("http://" + serverId + "/async/test", Map.class);

        Map body = responseEntity.getBody();

        System.out.println(body);


    }

    @RequestMapping("/test")
    public void test(){
        //异步调用无返回值
        asyncService.test();
        System.out.println("主线程");
    }

    @RequestMapping("/testReturn")
    public void testReturn() throws ExecutionException, InterruptedException {
        //异步调用有返回值
        Future<String> future = asyncService.testReturn();
        System.out.println(future.get());
        System.out.println("主线程");
    }
}
package com.example.demo.service.Impl;

import com.example.demo.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

@Service
public class AsyncServiceImpl implements AsyncService {

    @Async
    @Override
    public void test() {
        async();
    }

    /**
     * 有返回值的情况下,虽然异步业务逻辑是由新线程执行,但如果在主线程操作返回值对象,主线程会等待,还是顺序执行
     * @return Future<String>
     */
    @Async
    @Override
    public Future<String> testReturn() {
        async();
        return AsyncResult.forValue("测试异步调用有返回接口");
    }

    private void async(){
        System.out.println("进入异步调用");
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime);
    }


}

启动类上添加:

@EnableAsync    //开启异步调用

注意:spring 在扫描bean的时候会扫描方法上是否包含@Async注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用时增加异步作用。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就没有增加异步作用,我们看到的现象就是@Async注解无效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值