Scala DynamicVariable 对 ThreadLocal 的替代
Scala DynamicVariable's replacement of ThreadLocal
我不明白DynamicVariable
背后的代码和逻辑:
- 首先,您创建一个具有默认值的
DynamicVariable
实例...默认值???你想要每个线程的值!这是否意味着您可能在所有线程之间共享相同的默认值?达不到目的……还是?
- 然后我在所有示例中看到
withValue
几乎每次都创建一个新实例,或者?
例如ThreadLocal
有一个有意义的经典案例 SimpleDateFormat
每次创建都非常昂贵并且不是线程安全的:
import java.text.SimpleDateFormat;
static ThreadLocal<SimpleDateFormat> dateFormatTl = new ThreadLocal<SimpleDateFormat>();
...
// many threads execute this, check if there already exists a
// Thread-bound instance otherwise create a new one per-thread
if (dateFormatTl.get() == null) {
dateFormatTl.set(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss"));
}
// safely use the Thread-bound instance
SimpleDateFormat dateFormat = dateFormatTl.get();
dateFormat.format(new Date(java.util.Date.getTime()));
如何在 Scala 中使用 DynamicVariable
复制上述相同的功能?
// create with default instance ...
// what for? I don't want the same instance shared across all Threads!
val dateFormatDv = new DynamicVariable[SimpleDateFormat](new SimpleDateFormat("yyyy-dd-MM HH:mm:ss"))
// many threads execute this ...
// I see it is creating one new instance each time, and
// that is not what I want
dateFormatDv.withValue(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")) {
// safely use the Thread-bound instance, but this is a new one each time arrrggggg
dateFormatDv.value.format(new Date(java.util.Date.getTime()))
}
你想做的可以这样做:
Future {
dateFormatDv.withValue(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")) {
doStuffWithDateFormat(dateFormatDv.value)
doMoreStuffWithTheSameFormatInstance(dateFormatDv.value)
}
}
Future {
dateFormatDv.withValue(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")) {
useADifferentInstanceOfDateFormat(dateFormat.value)
}
}
至于默认值,只是让你设置,方便在当前线程使用,不用.withValue
doSomethingWithDefaultFormatInstance(dateFormat.value)
我猜 Scala 的 DynamicVariable
的 ThreadLocal
化更像这样:
// do only once and put in static scope within some Object
val dateFormatDv = new DynamicVariable[Option[SimpleDateFormat]](None)
// this is executed by different threads
def formatTimestamp(timestamp: Long): String = {
dateFormatDv.value match {
case None => dateFormatDv.value_=(Some(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")))
}
// safely use the Thread-bound instance
dateFormatDv.value.map(_.format(new Date(timestamp))).get
}
我不明白DynamicVariable
背后的代码和逻辑:
- 首先,您创建一个具有默认值的
DynamicVariable
实例...默认值???你想要每个线程的值!这是否意味着您可能在所有线程之间共享相同的默认值?达不到目的……还是? - 然后我在所有示例中看到
withValue
几乎每次都创建一个新实例,或者?
例如ThreadLocal
有一个有意义的经典案例 SimpleDateFormat
每次创建都非常昂贵并且不是线程安全的:
import java.text.SimpleDateFormat;
static ThreadLocal<SimpleDateFormat> dateFormatTl = new ThreadLocal<SimpleDateFormat>();
...
// many threads execute this, check if there already exists a
// Thread-bound instance otherwise create a new one per-thread
if (dateFormatTl.get() == null) {
dateFormatTl.set(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss"));
}
// safely use the Thread-bound instance
SimpleDateFormat dateFormat = dateFormatTl.get();
dateFormat.format(new Date(java.util.Date.getTime()));
如何在 Scala 中使用 DynamicVariable
复制上述相同的功能?
// create with default instance ...
// what for? I don't want the same instance shared across all Threads!
val dateFormatDv = new DynamicVariable[SimpleDateFormat](new SimpleDateFormat("yyyy-dd-MM HH:mm:ss"))
// many threads execute this ...
// I see it is creating one new instance each time, and
// that is not what I want
dateFormatDv.withValue(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")) {
// safely use the Thread-bound instance, but this is a new one each time arrrggggg
dateFormatDv.value.format(new Date(java.util.Date.getTime()))
}
你想做的可以这样做:
Future {
dateFormatDv.withValue(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")) {
doStuffWithDateFormat(dateFormatDv.value)
doMoreStuffWithTheSameFormatInstance(dateFormatDv.value)
}
}
Future {
dateFormatDv.withValue(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")) {
useADifferentInstanceOfDateFormat(dateFormat.value)
}
}
至于默认值,只是让你设置,方便在当前线程使用,不用.withValue
doSomethingWithDefaultFormatInstance(dateFormat.value)
我猜 Scala 的 DynamicVariable
的 ThreadLocal
化更像这样:
// do only once and put in static scope within some Object
val dateFormatDv = new DynamicVariable[Option[SimpleDateFormat]](None)
// this is executed by different threads
def formatTimestamp(timestamp: Long): String = {
dateFormatDv.value match {
case None => dateFormatDv.value_=(Some(new SimpleDateFormat("yyyy-dd-MM HH:mm:ss")))
}
// safely use the Thread-bound instance
dateFormatDv.value.map(_.format(new Date(timestamp))).get
}