在scala上创建线程局部对象

时间:2013-01-05 20:13:15

标签: multithreading scala singleton

我正在用scala编写一个计算库。类似的功能我组成本机scala单例对象,包含一堆程序和一些静态分配的内存,用于O(1)时态数据。

此方法适用于单线程使用。但是同时从不同的线程调用库函数可能会覆盖时态数据并给调用者提供错误的答案。

我可能只是复制这个库并通过在函数局部空间内移动所有静态分配的内存来编写线程安全版本。但我更喜欢通过定义线程局部变量来避免它。

scala可以吗?

2 个答案:

答案 0 :(得分:25)

只需使用Java的java.lang.ThreadLocal类来存储变量。

val tl = new ThreadLocal[String]
tl.set("fish")
tl.get   // "fish"

请注意,执行此操作会产生非零性能损失(我记得在我手中约为6 ns)。如果你正在做很轻量级的东西(例如递增索引),你可能会注意到速度的差异。

答案 1 :(得分:5)

自Java 8发布以来,有更多声明性方法来初始化ThreadLocal

<强> Scala的:

val local = ThreadLocal.withInitial[String](() => "init value");

Java中的模拟:

ThreadLocal<Cipher> local = ThreadLocal.withInitial(() -> "init value");

在Java 8发布之前,您必须执行以下操作:

<强> Scala的:

val local = new ThreadLocal[String]{
  override def initialValue = "init value"
}

Java中的模拟:

ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};

注意: 评估是懒惰的,因为您传递的java.util.function.Supplier lambda仅在调用ThreadLocal#get时进行评估,但之前未评估过值。