简体   繁体   English

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

[英]Synchronous behavior when use methods of Java CompletableFuture

I am using Java's CompletableFuture like this into a spring boot @Service : 我正在像这样在Java Boot的@Service使用Java的CompletableFuture:

@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;
    }

}

The process method is called form a method inside a @RestController : @RestController内部的方法称为process方法:

@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 only save some data to database according to its parameter. ChangeHistoryService::logChanges仅根据其参数将一些数据保存到数据库。 I have a microservice that makes a number of request to this "/processAttribute" endpoint and print all responses. 我有一个微服务,该微服务对此“ / processAttribute”端点发出许多请求并打印所有响应。

When I put a breakpoint in logChanges method, the microservice is waiting on some request but not all which makes me think that the ChangeHistoryService::logChanges not always runs async. 当我在logChanges方法中设置断点时,微服务正在等待某些请求,但并非所有请求都在等待,这使我认为ChangeHistoryService::logChanges并不总是运行异步。 If I don't supply the runAsync with a ExecutorService, the microservice blocks on more request but still not all. 如果我不为runAsync提供ExecutorService,则微服务会在更多请求时阻止,但仍不是全部。 From what I understood this is because method that process the request and logChanges method share same thread pool (ForkJoinPool?). 据我了解,这是因为处理请求的方法和logChanges方法共享同一线程池(ForkJoinPool?)。 Anyway, as I have another ExecutorService, logChanges should not runs independently? 无论如何,由于我还有另一个ExecutorService, logChanges不应独立运行吗? Or is something about how IDE treats breakpoints on async task? 还是关于IDE如何处理异步任务上的断点的事情? I am using IntelliJ IDEA. 我正在使用IntelliJ IDEA。

The problem was that the breakpoint suspends all threads and not only the thread that runs logChanges method. 问题在于断点会挂起所有线程,而不仅是运行logChanges方法的线程。 I fix this in Intellij IDEA by pressing right click on breakpoint and checked "Thread" checkbox, not "All": 我通过在断点上单击鼠标右键,然后选中“线程”复选框,而不是“全部”,来解决此问题:

在此处输入图片说明

You have a rather small threadpool, so it's no wonder that you can saturate it. 您的线程池非常小,因此可以饱和它也就不足为奇了。 The threads that process requests are not the same as the ones processing your CompletableFutures . 处理请求的线程与处理CompletableFutures的线程不同。 One is an internal component of the server, and the second one is the one you explicitly created, EXECUTOR . 一个是服务器的内部组件,第二个是您显式创建的组件EXECUTOR

If you want to increase the asynchronousness, try giving EXECUTOR some more threads and see how the behaviour changes accordingly. 如果要增加异步性,请尝试为EXECUTOR更多线程,然后查看行为如何相应地改变。 Currently the EXECUTOR is a bottleneck, since there are far more threads available for requests to run in. 当前, EXECUTOR是一个瓶颈,因为有更多线程可用于运行请求。

Note that by putting a breakpoint inside logChanges() you'll be blocking one thread in the pool, making it even more saturated. 请注意,通过在logChanges()内放置一个断点,您将阻塞池中的一个线程,使其更加饱和。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM