什么时候应该使用scala.util.DynamicVariable?

Fre*_*ind 46 scala thread-local

当我阅读scalatra的来源时,我发现有一些代码如下:

protected val _response   = new DynamicVariable[HttpServletResponse](null)
protected val _request    = new DynamicVariable[HttpServletRequest](null)
Run Code Online (Sandbox Code Playgroud)

有一个有趣的课程名称DynamicVariable.我看过这堂课的文件,但我不知道何时以及为什么要使用它?它有一个withValue()通常使用的.

如果我们不使用它,那么我们应该使用什么代码来解决它解决的问题?

(我是scala的新手,如果你能提供一些代码,那就太好了)

Vas*_*iuk 56

DynamicVariable是贷款和动态范围模式的实现.用例DynamicVariable是非常类似于ThreadLocalJava中(作为事实上,DynamicVariable使用InheritableThreadLocal在幕后) -它的使用,当你需要一个封闭的范围,其中每个线程都有它的变量的值的自己的副本内做一个计算:

dynamicVariable.withValue(value){ valueInContext =>
  // value used in the context
} 
Run Code Online (Sandbox Code Playgroud)

鉴于DynamicVariable使用可继承ThreadLocal,变量的值将传递给在上下文中生成的线程:

dynamicVariable.withValue(value){ valueInContext =>
  spawn{
    // value is passed to the spawned thread
  }
}
Run Code Online (Sandbox Code Playgroud)

DynamicVariable(和ThreadLocal)在Scalatra中使用的原因与它在许多其他框架(Lift,Spring,Struts等)中使用的原因相同 - 它是一种非侵入式的方式来存储和传递上下文(线程)特定的信息.

制作HttpServletResponseHttpServletRequest动态变量(以及因此绑定到处理请求的特定线程)只是在代码中的任何位置获取它们的最简单方法(不通过方法参数或任何其他方式显式).


ove*_*ink 24

Vasil已经很好地回答了这个问题,但我会添加一个可能进一步帮助理解的简单示例.

假设我们必须使用一些使用println()来编写遍历stdout的代码.我们希望此输出转到日志文件,但我们无权访问源.

  • println() 使用 Console.println()
  • Console.println()(幸运)是基于一个DynamicVariable[PrintStream]默认为java.lang.System.out
  • Console定义withOut只转发到动态变量withValue

我们可以用它来解决我们的问题:

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
Run Code Online (Sandbox Code Playgroud)


Han*_*Sun 18

这是一个最小的片段:

val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
  print
}
print
Run Code Online (Sandbox Code Playgroud)

输出将是:

withoutValue
withValue
withoutValue
Run Code Online (Sandbox Code Playgroud)