DynamicVariable in Scala
文章目录
scala.util.DynamicVariable
,这个类有点类似于 java 里面 ThreadLocal
,适合用来保存和传递上下文(Context)相关的信息。
Scala 的官方文档 是这么介绍的:
DynamicVariables
提供了一种绑定机制,即变量的当前值是通过动态范围来查找的,但是对变量自身的访问是在静态范围里的。
这句话看着挺抽象的。简单的说,就和类名的含义一致,变量的值是动态获取的。使用 value
方法可以获取到当前的值。通过 withValue
方法设置新的值,但是这个新设置的值只有在 withValue
方法的第二个参数,一个无参数的闭包,执行的时候时候有效。一旦第二个参数执行完毕后,变量的值重新回到以前。类似于一个栈。
|
|
Each thread gets its own stack of bindings. When a new thread is created, the DynamicVariable gets a copy of the stack of bindings from the parent thread, and from then on the bindings for the new thread are independent of those for the original thread.
在 withValue
中创建一个新的线程,该线程从 DynamicVariable
中取出当前绑定的值,此后该值和父线程里面的绑定值就再无关联了。
实际上,从 DynamicVariable
的源码来看,就是基于 InheritableThreadLocal
实现的。代码也并不复杂:
|
|
这个问题很好地说明了我们应该怎么用 DynamicVariable
。
> It’s a non-intrusive way to store and pass around context(thread)-specific information.
其中一个答案里提到 Concole.println
这个方法的实现,很有意思。
println()
即Console.println()
Console.println()
是基于DynamicVariable[PrintStream]
, 默认值是java.lang.System.out
Console
提供了一个withOut
,实际上就是对内部动态变量的withValue
方法的封装1 2 3 4
def noisy() { println("robot human robot human") } noisy() // prints to stdout val ps = new java.io.PrintStream("/tmp/mylog") scala.Console.withOut(ps) { noisy() } // output now goes to /tmp/mylog file
参考
文章作者 jrthe42
原始链接 https://blog.jrwang.me/2018/dynamic-variable-in-scala/
上次更新 2019-09-12
许可协议 CC BY-NC-ND 4.0