为什么从IntelliJ运行时Future永远不会完成?

huangapple go评论58阅读模式
英文:

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很可能会等待该线程结束,然后在Futureprintln完成之前关闭流,因为它在另一个线程上执行。

尝试运行.map,并将所有内容包装在Await.result(Duration.Inf, future)中以确保阻塞,或者在foreachprintln之前添加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.

huangapple
  • 本文由 发表于 2023年6月8日 19:53:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76431587.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定