简体   繁体   中英

CompletableFuture always throw time out exception

I have a piece of code like below

protected List<AMQMessage> waitForReceivedRawMessageFromActiveMq(AMQConsumerMessageListener listener) {
CompletableFuture<List<AMQMessage>> completableFuture = CompletableFuture.supplyAsync(() -> {
    while (listener.getMessageList().isEmpty()) {}
    return listener.getMessageList();
});
List<AMQMessage> rawMessage = Lists.newLinkedList();
try {
    rawMessage = completableFuture.get(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
    e.printStackTrace();
}
return rawMessage;
}

It always throws TimeoutException , I don't know what's happening. But when I have toggled debug point in IDEA, it work. Is there anyone can explain for me, pleaseeee.

This is happening because of insufficient synchronization. You are updating the listener 's messageList in some thread, but the thread that is running your supplyAsync() (the ForkJoin commonPool's worker thread by default) doesn't see that change, and so the while loop runs forever. Sometimes it may see that change, but it's not guaranteed. Perhaps the debugger handles memory visibility of threads differently.

Solution : Try adding synchronized to your getMessageList() and setMessageList() methods. And/or use a synchronized list (like Collections.synchronizedList(...) or CopyOnWriteArrayList , etc.), depending on whether you are updating the reference of the list variable, or updating its contents.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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