从@Async 函数调用中取回数据

Getting data back from @Async function call

您好,我是 java 中的多线程新手。有人可以帮我解决这个问题吗:

我的服务:

@Async
public List<String> doSomething(int a){
    //Do something
    return list;
}

Springboot应用:

@SpringBootApplication
@EnableAsync
public class Test {

    public static void main(String[] args) {
        SpringApplication.run(Test.class, args);
    }

}

异步配置:

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name ="taskExecutor")
    public Executor taskExecutor(){
        ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("userThread-");
        executor.initialize();
        return executor;
    }
}

控制器:

@RestController
public class Controller{
    
    @Autowired
    private Service service;

    @GetMapping("test")
    public List<String> getAll(){
        return service.doSomething(1);
    }
}

当我点击邮递员的这个获取请求时,它在响应中显示为空白。我知道我的调用是异步进行的,响应甚至在我的方法被调用之前就返回了。有什么方法可以通过更改我的邮递员或 spring 启动应用程序

中的某些设置来查看此响应

你可以returnCompletableFuture。当 CompleteableFuture 完成时,您将收到 http 响应。

服务:

@Async
public CompletableFuture<List<String>> doSomething() {
    return CompletableFuture.completedFuture(Arrays.asList("1", "2", "3"));
} 

控制器:

@GetMapping("test")
public CompletableFuture<List<String>> getAll(){
    return service.getAll();
}

如果您想使用异步,我会将您的单个请求拆分为所谓的“启动任务”和“获取任务结果”请求。您的应用程序 returns“启动任务”请求的“请求 ID”。然后在执行“获取任务结果”时使用“请求 ID”。这样的场景在批处理任务中很常见。如果您使用 Spring,您可能会对调查 Spring Batch 框架感兴趣,该框架具有 Start/Stop/Restart 工作功能等。

如果您想异步处理请求,但又希望 API 客户端在完成处理后接收响应,这样从客户端的角度来看,请求处理看起来仍然是同步的,关键是使用 Servlet3 asynchronous processing 功能。

您无需将其配置为使用 @Aysnc 在服务级别异步执行。而是将控制器方法配置为 return CompletableFuture。在幕后,它会触发Servlet3的异步请求处理,它会在接收请求的HTTP线程之外的另一个线程中处理请求。

所以您的代码应该类似于:

public class Service {
    
    //No need to add @Async
    public List<String> doSomething(int a){
        return list;
    }
}


@RestController
public class Controller{
    
    @Autowired
    private Service service;

    @GetMapping("test")
    public CompletableFuture<List<String>> getAll(){
        return CompletableFuture.supplyAsync(()->service.doSomething(1));
    }
}

spring-mvc支持的Servlet3异步请求处理,可以参考this开始的系列博文。