使用 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":
我正在使用 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":