首页 > 解决方案 > Java 相当于 Scala 的未来?

问题描述

我正在寻找 Java 中与 Scala 的未来等价的东西。

我正在寻找一种允许我将任务(Runnables / Callables)提交到我选择的特定线程池的构造类型,返回期货允许我在它发生时将一些逻辑(以非阻塞方式)链接到它完成。像这样的东西:

var executor = Executors.newCachedThreadPool();
executor.submit(() -> {
  Thread.sleep(5000);
  return 666;
}.onComplete(v -> System.out.println(v));

Java 的线程池(可通过Executors单例获得)似乎总是返回标准 Java Futures,它只允许我调用阻塞get()。另一方面,据CompletableFuture我所知, 更类似于 Scala 的承诺,并且不依赖于线程池。

Java 是否提供了我正在寻找的东西?Java 领域的人们如何处理这些类型的操作?

标签: javamultithreadingscalaconcurrency

解决方案


想要回调地狱吗?那是一个新的。

据我所知,它更类似于 Scala 的承诺,并且不依赖于线程池。

不正确。我认为 CompletableFuture 正是你想要的:)

将使用一个默认执行器,但如果您愿意,也可以显式指定一个 -supplyAsyncrunAsync方法具有重载,您可以在其中传递显式执行器,并且链中的所有内容都使用您未来的任何东西链接使用。

CompletableFuture.supplyAsync(() -> {
    Thread.sleep(5000);
    System.out.println("Helloooo there, from stage 1!");
    return 666;
}).whenCompleteAsync((result, exception) -> {
    Thread.sleep(5000);
    System.out.println("Coming to you live from stage 2: " + result);
    // result is null if an error has occurred in stage 1.
    // exception is null if an error did not occur.
});

注意:如果你把它扔进 a psv main,请确保在.get()最后添加 a ;否则,虚拟机将在未来有机会实际完成工作之前退出。然后,您将看到:

> Helloooo there, from stage 1!
> Coming to you live from stage 2: 666

第一个字符串在约 5 秒后出现。10 后的第二个,然后 VM 退出。


请注意,看起来java 的未来不是未来。java中的期货遭受回调地狱的困扰,并且没有解决“红/蓝”方法问题(这就是从异步代码调用(可能)阻塞的任何东西是一个非常有问题的错误:很难静态检测,几乎不可能进行测试,但会完全破坏您在生产中的性能。不幸的是,很难意识到您不小心做了一些阻塞的事情,并且很少有现有的 API 和库都记录它们是否这样做,然后承诺永远不会更改此内容而不考虑更改向后不兼容的更新并适当地管理其版本以反映这一点)。

这些都是可以解决的问题,但并不容易:Java 将需要“异步”或类似的,并且还需要认真努力添加文档以及可能在编译时检查的内容,例如使用注释。

但这些都不是java未来的任何地方。然而,即将出现的(现在很快,最多一年或两年的时间跨度)是“Project Loom”——它向 Java 添加了轻量级线程(“纤维”):它们代表执行状态,但它们本身不能运行在另一个核心上。你可以赚几百万,没问题。然后你只需写:

int priceyOp1 = doSomethingThatTakesLong();
int priceyOp2 = thisIsAlsoSlow(priceyOp1);

并将整个东西推入光纤,甚至还有一个漏斗概念,其中线程池将意识到它当前正在运行的光纤现在被阻塞,然后从池中取出另一条光纤并运行一段时间。这并没有让futures完全没有意义,但这可能意味着futures 将保持小众,并且异步/回调地狱不会很快得到解决。


推荐阅读