如何在 Actor 中安全地使用 ThreadLocal 缓存?

发布于 2024-09-30 15:11:47 字数 498 浏览 7 评论 0原文

我的应用程序最终通过 Actor 进行大量后台处理,特别是加载 Mapper 实例,然后对它们进行一些工作。这是非常重复的,我想在我的 Actor 代码中缓存其中一些查找。

我通常会使用 ThreadLocal 来实现此目的。然而,由于线程初始化是由 Actor 线程池处理的,因此初始化并随后清除 ThreadLocal 的唯一位置似乎是在 Actor 接收传入消息的 PartialFunction 中。

我现在要做的是在我的 Actor 中创建另一个方法,如下所示:

override def aroundUpdates[T](fn: => T) : T = {
  clientCache.init {
    fn
  }
}

其中 init 方法处理在 finally 块中清除 ThreadLocal。我不喜欢这种方法,因为 aroundUpdates 的存在只是为了设置缓存,而且它闻起来像代码味道。

有更好的方法吗?

My app ends up doing a lot of background processing via Actors, specifically loading Mapper instances and then doing some work upon them. It's very repetitive and I'd like to cache some of these lookups across my Actor code.

I'd typically use a ThreadLocal for this. However, since the thread initialization is handled by the Actor thread pool, it seems like the only place to initialize and subsequently clear the ThreadLocal would be in the actor's PartialFunction which receives incoming messages.

What I'm doing now is to create another method in my Actor, like this:

override def aroundUpdates[T](fn: => T) : T = {
  clientCache.init {
    fn
  }
}

Where the init method handles clearing the ThreadLocal in a finally block. I don't like this approach because aroundUpdates only exists for the purpose of setting up the cache and it smells like a code smell.

Is there a better way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟雨凡馨 2024-10-07 15:11:47

您不需要使用线程局部变量:在单个反应期间,您在单个线程中运行。因此你可以只使用普通的var。更重要的是,因为您的反应是顺序的并且参与者子系统为您管理同步,所以您可以(如果您愿意)从不同的反应访问状态:

def act = loop {
  var state : String = null

  def foo = state = "Hello"
  def bar = { println(state + " World"); state = null }
  def baz = println(state + " Oxbow")
  react {
    case MsgA => foo; bar
    case MsgB => baz
  }

}

因此线程局部变量不会任何感觉都可以用在你自己的反应中!

You don't need to use thread-locals: during a single reaction, you are running in a single thread. Hence you could just use a normal var. What's more, because your reactions are sequential and the actor subsystem manages synchronization for you, you could (If you want) access the state from different reactions:

def act = loop {
  var state : String = null

  def foo = state = "Hello"
  def bar = { println(state + " World"); state = null }
  def baz = println(state + " Oxbow")
  react {
    case MsgA => foo; bar
    case MsgB => baz
  }

}

Hence thread locals make no sense whatsoever to use in your own reactions!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文