我对JMM和Scala期货有疑问。
在以下代码中,我具有不可更改的 Data 类。我在一个线程(在Future apply主体内部)中创建它的一个实例,然后订阅完成事件。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Hello extends App {
Future {
new Data(1, "2")
}.foreach { d =>
println(d)
}
Thread.sleep(100000)
}
class Data(var someInt: Int, var someString: String)
我们可以保证:
答案 0 :(得分:1)
完成happens-before
回调执行。
免责声明:我是主要贡献者。
答案 1 :(得分:0)
我有一个类似的问题,我发现的是-
1)在文档Intellij中,对我来说很方便,它显示为
一旦值可用,将来会异步处理该值...
2)在https://docs.scala-lang.org/overviews/core/futures.html上说
结果将在将来完成后提供。
从根本上讲,我找不到明确指出存在内存障碍的地方。我怀疑,但这是一个安全的假设。否则,该语言将无法正常工作。
答案 2 :(得分:0)
您可以通过查看Promise
/ DefaultPromise
/ Future
的源代码来很好地了解这一点,该源代码在执行上下文中安排foreach
的回调/将其添加到侦听器,而无需任何特殊的逻辑来要求它在原始线程上运行...
但是您也可以通过尝试设置执行上下文和线程来进行实验性验证,以便在创建Future
的{{1}}完成时已经将其他内容排队等待执行。< / p>
Data
我的输出:
在以下位置创建的数据:pool- $ n-thread-1
数据在以下位置完成:pool- $ n-thread-2
2。
在这里比我想要的要自信,但是我会给它一个机会:
是的
{p}implicit val context = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(2))
Future {
new Data(1, "2")
println("Data created on: " + Thread.currentThread().getName)
Thread.sleep(100)
}.foreach { _ =>
println("Data completed on: " + Thread.currentThread().getName)
}
Future { // occupies second thread
Thread.sleep(1000)
}
Future { // queue for execution while first future is still executing
Thread.sleep(2000)
}
是DefaultPromise
的基础构造,它包装了一个原子引用,其行为就像一个volatile变量。由于更新结果的写操作必须在将结果传递给侦听器的读取操作之前进行,因此它可以运行回调,因此JMM易失性变量规则将其转换为Future
关系。
答案 3 :(得分:-1)