【问题标题】:CompletableFuture always throw time out exceptionCompletableFuture 总是抛出超时异常
【发布时间】:2020-11-18 05:06:53
【问题描述】:

我有一段如下代码

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

它总是抛出TimeoutException,我不知道发生了什么。 但是当我在 IDEA 中切换调试点时,它就可以工作了。 有没有人可以帮我解释一下,拜托。

【问题讨论】:

  • 你到底在用调试器做什么?
  • 我在return listener.getMessageList(); 行中添加调试点,以上代码工作正常。
  • 究竟做什么。您在该行放置一个断点,调试您的程序。那么是断点命中了吗?
  • 没错。但是当我关闭断点时,上面的代码就不再起作用了。
  • 什么是AMQConsumerMessageListener?现在这个问题毫无意义,投票结束。

标签: java java-8 completable-future


【解决方案1】:

这是由于同步不足而发生的。您正在某个线程中更新listenermessageList,但是运行supplyAsync() 的线程(默认情况下是ForkJoin commonPool 的工作线程)没有看到这种变化,因此while循环永远运行。有时它可能看到这种变化,但不能保证。也许调试器以不同方式处理线程的内存可见性

解决方案:尝试将synchronized 添加到您的getMessageList()setMessageList() 方法中。和/或使用同步列表(如Collections.synchronizedList(...)CopyOnWriteArrayList 等),具体取决于您是更新列表变量的引用,还是更新其内容。

【讨论】:

  • 你能和我分享一篇关于它的文章吗?我其实不知道他们的机制
  • 您可能是对的,但在不知道 AMQConsumerMessageListener 是什么或做什么的情况下,您不能简单地假设将同步添加到这些方法(无论如何这可能太多了,volatile 阅读/写在适当的地方就足够了)会做正确的事情。
猜你喜欢
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-03
相关资源
最近更新 更多