Spring Boot 3.2+虚拟线程并行调用外部服务的正确实现方式
关于Spring Boot 3.2中RestClient结合虚拟线程并行调用外部服务的问题
1. 顺序调用代码的问题
你给出的第一种写法是同步串行执行,完全无法实现并行调用。代码会先等待performGetRequest(uri1)返回结果后,才会执行performGetRequest(uri2),两个请求依次执行,完全没用到虚拟线程的并行能力,不符合你并行调用的需求。
2. Future写法的核心注意点
第二种写法要实现并行,关键看performGetRequest的实现逻辑:
- 如果这个方法只是单纯同步调用RestClient(比如
return restClient.get().uri(uri).retrieve().body(String.class);),那直接返回Future毫无意义——你必须把每个请求任务提交到虚拟线程池,让它们在独立的虚拟线程上运行,才能真正并行。正确的写法示例:
ExecutorService virtualThreadExecutor = Executors.newVirtualThreadPerTaskExecutor(); Future<String> response1 = virtualThreadExecutor.submit(() -> performGetRequest(uri1)); Future<String> response2 = virtualThreadExecutor.submit(() -> performGetRequest(uri2)); String result1 = response1.get(); String result2 = response2.get(); virtualThreadExecutor.shutdown();
- 要是你没把任务提交到虚拟线程池,直接返回
Future本质还是在当前线程顺序执行两个请求,达不到并行效果。
3. 是否需要手动创建虚拟线程池?
虽然你配置了spring.threads.virtual.enabled=true,但这个配置仅让Spring的默认TaskExecutor(比如@Async注解使用的线程池)改用虚拟线程,不会自动帮你并行执行代码里的同步调用。
所以要实现并行调用,你需要手动创建虚拟线程池(比如Executors.newVirtualThreadPerTaskExecutor()),或者注入Spring提供的TaskExecutor(启用虚拟线程后,它已经是虚拟线程池)。
另外,用try-with-resources包裹ExecutorService是更安全的做法,它会自动关闭线程池,无需手动调用shutdown():
try (ExecutorService service = Executors.newVirtualThreadPerTaskExecutor()) { Future<String> response1 = service.submit(() -> performGetRequest(uri1)); Future<String> response2 = service.submit(() -> performGetRequest(uri2)); return response1.get() + response2.get(); }
补充:Spring 6.1+的简化异步写法
Spring Boot 3.2基于的Spring 6.1提供了更简洁的异步调用方式,结合虚拟线程可以这样写:
CompletableFuture<String> response1 = CompletableFuture.supplyAsync(() -> restClient.get().uri(uri1).retrieve().body(String.class), Executors.newVirtualThreadPerTaskExecutor() ); CompletableFuture<String> response2 = CompletableFuture.supplyAsync(() -> restClient.get().uri(uri2).retrieve().body(String.class), Executors.newVirtualThreadPerTaskExecutor() ); return CompletableFuture.allOf(response1, response2) .thenApply(v -> response1.join() + response2.join()) .join();
也可以直接注入Spring的TaskExecutor替代手动创建的线程池,更贴合Spring生态。
内容的提问来源于stack exchange,提问作者William N
相关产品推荐
相关产品推荐

