¿Cuándo deberíamos usar scala.util.DynamicVariable?
thread-local (3)
Este es un fragmento mínimo:
val dyn = new DynamicVariable[String]("withoutValue")
def print=println(dyn.value)
print
dyn.withValue("withValue") {
print
}
print
El resultado será:
withoutValue
withValue
withoutValue
Cuando leí la fuente de scalatra, encontré que hay algunos códigos como:
protected val _response = new DynamicVariable[HttpServletResponse](null)
protected val _request = new DynamicVariable[HttpServletRequest](null)
Hay una clase interesante llamada DynamicVariable
. He visto el documento de esta clase, pero no sé cuándo ni por qué deberíamos usarlo. Tiene un withValue()
que generalmente se usa.
Si no lo usamos, ¿qué código deberíamos usar para resolver el problema resuelto?
(Soy nuevo en Scala, si puedes proporcionar algún código, será genial)
Vasil lo responde bien, pero agregaré un ejemplo simple adicional que podría ayudar a comprender mejor.
Supongamos que debemos usar algún código que use println () para escribir todo sobre stdout. Queremos que esta salida vaya a un archivo de registro, pero no tenemos acceso a la fuente.
-
println()
usaConsole.println()
-
Console.println()
(afortunadamente) se basa enDynamicVariable[PrintStream]
que por defecto esjava.lang.System.out
-
Console
definewithOut
que simplemente reenvía a la variable dinámicawithValue
Podemos usar esto para simplemente arreglar nuestro problema:
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
DynamicVariable
es una implementación del préstamo y los patrones de alcance dinámico. Use-case de DynamicVariable
es bastante similar a ThreadLocal
en Java (de hecho, DynamicVariable
usa InheritableThreadLocal
detrás de las escenas) - se usa cuando se necesita hacer un cálculo dentro de un alcance cerrado, donde cada hilo tiene su propia copia del valor de la variable:
dynamicVariable.withValue(value){ valueInContext =>
// value used in the context
}
Dado que DynamicVariable
usa un ThreadLocal
heredable, el valor de la variable se pasa a los hilos generados en el contexto:
dynamicVariable.withValue(value){ valueInContext =>
spawn{
// value is passed to the spawned thread
}
}
DynamicVariable
(y ThreadLocal
) se usa en Scalatra por la misma razón que se usa en muchos otros marcos (Lift, Spring, Struts, etc.): es una forma no intrusiva de almacenar y transmitir información específica de contexto (hilo).
Hacer las variables dinámicas HttpServletResponse
y HttpServletRequest
(y, por lo tanto, vinculante a un hilo específico que procesa la solicitud) es simplemente la forma más fácil de obtenerlas en cualquier parte del código (no pasando por los argumentos del método o de ningún otro modo explícito).