当前位置: 首页 > 知识库问答 >
问题:

根据CompletableFuture的结果做一些事情,而不阻止Java中的线程

厍和颂
2023-03-14

首先,我不太熟悉CompletableFuture。我试图做的是通过CompletableFuture从数据库中检索数据,然后对结果进行处理。使用CompletableFuture#join/get处理数据会阻塞线程。

CompletableFuture<IPlayerData> future = playerDataManager.getOfflinePlayerDataAsync(target);
IPlayerData result = future.join(); //blocks the thread e.G. if database isn't reachable
//work with the result (maybe callback?)

请注意,我试图不在一个单独的线程上运行上面的代码部分。有没有什么好的办法来做到这个不堵?我很确定我的代码有问题(可能是GetOfflinePlayerAsync?)我真的不知道该怎么继续。

@Override
  public CompletableFuture<IPlayerData> getOfflinePlayerDataAsync(OfflinePlayer player) {
    CompletableFuture<IPlayerData> future = new CompletableFuture<>();
    DiscoBox.schedule(() -> future.complete(handler.loadObject(player.getUniqueId().toString()))).createAsyncTask(); //gets object from database
    return future;
  }

共有1个答案

关志勇
2023-03-14

如果您不想阻止“接收”值的线程,您可以在以下情况下执行以下操作:

// Get the value if it is available
if (future.isDone()) {
     value = future.get();
     // do something with value
}

// Get the value if it is available in the next second
try {
    value = future.get(1, TimeUnit.SECONDS);
    // do something with  value
} catch (TimeoutException ex) {
    // ho hum
}

有了completablefuture,还有其他非阻塞的替代方案;例如。

value = future.getNow(someDefault);
if (value != someDefault) {
     // do something with value
}

注意,使用以上所有内容,您只尝试一次获取值。如果一次尝试还不够,你可能会想做这样的事情:

while (!future.isDone()) {
     // do something else
}
value = future.get();
// do something with value

但这可能会阻塞线程...实际上。在将来完成之前,您不能越过上面代码的结尾。

如果您不关心值何时可用,因为您不打算用它做任何事情,那么您可以简单地忽略future

最后,异步传递值的另一种方法是使用回调。您可以提供一个回调函数作为GetOfflinePlayerDataAsync方法的参数。那么您可以提供如下结果:

    DiscoBox.schedule(() -> callback(handler.loadObject(...))).createAsyncTask();

回调可以简单地将返回的值赋给某个共享变量,也可以执行更复杂的操作。关键是它将在异步任务的线程上执行,而不是在调用GetOfflinePlayerDataAsync的线程上执行。

 类似资料:
  • 我的java代码中有一个异步链,我想在某个超时后停止它,所以我创建了一个包含一些线程的线程池,并像这样调用CompletableFuture 然后我有一个循环方法,从数据库加载数据并对其执行一些任务,一旦所有CompletableFutures都完成了,它就会再次执行 我的问题是task6,它有一个非常密集的任务(它是一个网络连接任务,有时会永远挂起)。我注意到我的orTimeout在30秒后被正

  • Zookeeper实现了一个核心的操作集合,使得对于许多分布式应用非常常见的任务得以实现。你知道多少个应用是需要一个master,或者需要追踪哪个进程是可相应的?然而,Zookeeper不会为你实现那些任务。它不会选举一个领导者,也不会追踪那些活着的进程。相反,它提供了许多工具来实现这些任务。开发者自己觉得他们要实现的是哪种协同任务。

  • 问题内容: 我有一个实现可运行的线程类和一个int计数器作为实例变量。两种同步方法add和sub。当我以某种方式运行测试类时,它几次会输出错误的结果。据我了解,当方法同步时,整个对象将被锁定以供其他线程访问,这种逻辑每次我们都应该获得相同的结果正确吗?事实并非如此。我想念什么吗? 我的机器是Windows 7、64位。 测试类 结果 注意: 您可能需要进行几次运行才能产生这种不一致。 问题答案:

  • 在阅读了Oracle站点上的这篇文章https://community.Oracle.com/docs/doc-995305之后,我将尝试实现“Some Two-to-One selection patterns”段落中描述的模式。这最后一类模式还包含二对一模式。但是这次不是执行一次下游元素,而是完成两个上游元素,当两个上游元素中的一个完成时执行下游元素。例如,当我们要解析域名时,这可能会证明非常

  • 主要内容:1.测试,2.使用FactoryBean与 自己创建对象对比,3.FactoryBean 流程分析,4.总结FactoryBean就是生成Bean的, 其目的就是为了创建对象 FactoryBean 就是一个工厂Bean,相当于将工厂类放到了Spring中管理、当获取此Bean的时候返回的是此工厂生成的Bean。需要经过完整的一系列过程才可以创建出Bean 1.测试 当创建对象的过程复杂时可使用BeanFactory,调用方只需要注入就可使用 FactoryBean使创建对象操作 更加

  • 我有一个JButton,可以让我的JTextArea可见: 在第一次单击、第三次单击、第五次单击时,。。。在JButton上,JTextArea应该出现: 在第二次单击、第四次单击、第六次单击时,。。。在JButton上,JtextArea应该消失: 帮助被大大评价!