英文:
Why is a Future never completed when running from IntelliJ
问题
如果我运行以下代码:
implicit val ec = ExecutionContext.Implicits.global
def f(): Future[String] = Future("Hello")
f().foreach(println)
如果我在 Scala shell 中运行这段代码,会打印出 "Hello"。但是,如果我在 IntelliJ 中使用应用程序配置运行,future 永远不会完成,因为没有任何输出。我需要在最后添加一行代码。例如,这样可以让我得到 "Hello" 然后是 "World":
implicit val ec = ExecutionContext.Implicits.global
def f(): Future[String] = Future("Hello")
f().foreach(println)
println("World")
这是一个特性还是一个 bug?
英文:
Say I run the following code:
implicit val ec = ExecutionContext.Implicits.global
def f(): Future[String] = Future("Hello")
f().foreach(println)
If I run this in a scala shell "Hello" is printed out. But if I run this from within IntelliJ using an Application Configuration the future is never completed as nothing is output. I need to add a line of code at the end. So for example this will give me "Hello" and then "World":
implicit val ec = ExecutionContext.Implicits.global
def f(): Future[String] = Future("Hello")
f().foreach(println)
println("World")
Is this a feature or a bug?
答案1
得分: 4
foreach
不会阻塞。它会安排操作在线程池上执行... 立即返回Unit
。将其视为"发射并忘记"。
当在shell中运行时,当前操作结束后,您会返回到提示符,然后在不久之后,Future
将运行并打印结果。但这个时间非常短,您可能不会注意到它。
在IntelliJ中,当操作结束时,IDE很可能会等待该线程结束,然后在Future
的println
完成之前关闭流,因为它在另一个线程上执行。
尝试运行.map
,并将所有内容包装在Await.result(Duration.Inf, future)
中以确保阻塞,或者在foreach
的println
之前添加Thread.sleep(10000)
。您将会看到在打印"Hello"之前,您能够输入新命令。
英文:
foreach
is not blocking. It schedules operation to be executed on a thread pool... and returns Unit
immediately. Read it as "fire and forget".
When you run it in shell the current operations ends, you'll return to the prompt and some short time after than Future would run and print result. But the time would be very short and you might not notice it.
In IntelliJ when operation ends, IDE most likely waits for this one thread to end, and closes stream before future println finishes because it happens on another Thread.
Try running .map
and wrapping everything in Await.result(Duration.Inf, future)
to ensure blocking OR add Thread.sleep(10000)
in foreach
before println
. You'll see that you are able to type new command before Hello
is printed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论