以下代码:
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import scala.util.DynamicVariable
import scala.concurrent.ExecutionContext.Implicits.global
object Main {
def main(args: Array[String]) = {
val a = new DynamicVariable(1)
a.withValue(2) {
println(a.value)
Await.result(Future(println(a.value)), Duration.Inf)
}
}
}
正在打印:
2
1
但DynamicVariable依赖于InheritableThreadLocal
,其在doc:
此类扩展ThreadLocal以提供继承 从父线程到子线程的值:当子线程是 创建后,子进程将接收所有可继承的初始值 父对象具有值的线程局部变量。
这是否意味着InheritableThreadLocal实际上无效?
答案 0 :(得分:3)
可能我不对,但在我的例子中,我认为在2个线程之间没有父/子关系。
运行Future
的线程是导入的global
执行上下文中的一个线程。我认为这个执行上下文是在withValue
的第二个参数中的thunk开始执行之前创建的。
因此,您提供的文档中的摘录可能不适用于此情况。
如果我错了,请纠正我,因为我也想更好地理解动态变量概念。
答案 1 :(得分:1)
另一个猜测:
TL; DR:Future.apply{...}
不生成子线程,它适用于从隐式执行上下文获取的任何线程,在本例中为global
。
您的情况会发生什么:
a
main
和a.withValue(2) { println(a.value)
在某个线程T1上执行,该线程现在有a.value
堆栈[1, 2]
。Future.apply{println(a.value)}
时,您的global
执行上下文发生,为您提供另一个堆栈T2
的{{1}}帖子。[1]
获得输出2
,从T1
1
Scastie /我的轻量级设置会发生什么:
T2
的动态变量a
[1]
在某个线程a.withValue(2) { println(a.value); ... }
上运行,该线程现在具有堆栈T1
。[1, 2]
执行上下文在同一个帖子上运行global
Future.apply
T1
从同一个帖子Future.apply{println(a.value)}
2
顶部获取值[1,2]
总结:
T1
和T1
,则会得到输出“2 1”。T2
的{{1}}中获得相同的T1
,那么您将得到“2 2" 这看起来有道理吗?
答案 2 :(得分:1)
以下是使事情有效的文章:
http://stevenskelton.ca/threadlocal-variables-scala-futures/
基本上我们需要实现自定义ForkJoinPool
,我们复制DynamicVariables的值。这不是很好的解决方法,但它确实有效。
你们的评论和答案都是正确的 感谢