使用 Java CompletableFuture 方法时的同步行为

Synchronous behavior when use methods of Java CompletableFuture

我正在使用 Java 的 CompletableFuture 像这样进入 spring 启动 @Service:

@Service
public class ProcessService {

    private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(3);

    @Autowired
    ChangeHistoryService changeHistoryService;

    public Attribute process(Attribute attribute) {
        //some code

        CompletableFuture.runAsync(() -> changeHistoryService.logChanges(attribute), EXECUTOR);

        return attribute;
    }

}

process 方法是从 @RestController:

中的方法调用的
@RestController
public class ProcessController {


    @Autowired
    ProcessService processService;

    @RequestMapping(value = "/processAttribute",
            method = {RequestMethod.POST},
            produces = {MediaType.APPLICATION_JSON_VALUE},
            consumes = {MediaType.APPLICATION_JSON_VALUE})
    public Attribute applyRules(@RequestBody Attribute attribute) {

        Attribute resultValue = processService.service(attribute);

        return resultValue;
    }

}

ChangeHistoryService::logChanges只根据参数保存部分数据到数据库。 我有一个微服务,它向这个“/processAttribute”端点发出大量请求并打印所有响应。

当我在 logChanges 方法中放置断点时,微服务正在等待一些请求,但不是所有请求,这让我认为 ChangeHistoryService::logChanges 并不总是异步运行。如果我不为 runAsync 提供 ExecutorService,微服务会在更多请求时阻塞,但仍然不是全部。 据我了解,这是因为处理请求的方法和 logChanges 方法共享同一个线程池(ForkJoinPool?)。 无论如何,因为我有另一个 ExecutorService,logChanges 不应该独立运行吗?或者是关于 IDE 如何处理异步任务的断点?我正在使用 IntelliJ IDEA.

你有一个相当小的线程池,所以难怪你可以使它饱和。处理请求的线程与处理您的 CompletableFutures 的线程不同。一个是服务器内部组件,第二个是你明确创建的,EXECUTOR.

如果您想增加异步性,请尝试给 EXECUTOR 一些线程,然后看看行为如何相应地发生变化。目前 EXECUTOR 是一个瓶颈,因为有更多的线程可用于 运行 in.

的请求

请注意,通过在 logChanges() 内放置一个断点,您将阻塞池中的一个线程,使其更加饱和。

问题是断点暂停了所有线程,而不仅仅是运行 logChanges 方法的线程。我在 Intellij IDEA 中通过右键单击断点并选中 "Thread" 复选框来修复此问题,而不是 "All":