play.api.cache.Cache.getOrElse函数是否安全?

时间:2013-05-31 16:56:09

标签: scala caching concurrency playframework playframework-2.1

我正在使用该方法来缓存使用http调用的函数的结果。 我的代码看起来像这样,http可能已经很好了。

  def myData: Iterable[String] = {
    Cache.getOrElse[Iterable[String]](cacheKey, cacheExpiration)(Await.result(myHttpCallFunction(), Duration.apply(500, TimeUnit.MILLISECONDS)))
  }

我曾经把它作为

  val myData: Iterable[String] = Await.result(myHttpCallFunction(), Duration.apply(500, TimeUnit.MILLISECONDS))

我的代码线程现在安全吗?或者我应该做些别的事。我必须说我对斯卡拉很新,而且我对内心的工作并不十分熟悉。 如果它不是线程安全的:我怎么能这样做?

1 个答案:

答案 0 :(得分:4)

根据源代码,无论缓存实现如何,它都是线程安全。

def getOrElse[A](key: String, expiration: Int = 0)(orElse: => A)(implicit app: Application, m: ClassManifest[A]): A = {
    getAs[A](key).getOrElse {
      val value = orElse
      set(key, value, expiration)
      value
    }
  }

想想这个场景:

  1. 第一个请求是在时间戳100毫秒
  2. 缓存中不存在
  3. 键,因此执行或Else 以初始化缓存值,假设需要50ms才能完成
  4. 第二个请求以时间戳120ms进入相同的密钥
  5. 因为第一个 orElse 尚未完成,因此在缓存中找不到任何值,因此再次执行 orElse 以初始化缓存值
  6. 在时间戳上150ms,首先或Else 返回并保存到地图
  7. 在时间戳上160ms,第三个请求进入相同的密钥。缓存值将立即返回
  8. 在时间戳170毫秒,第二个或Else 返回。即使值已缓存,缓存也会被覆盖
  9. 因此,播放缓存插件有利于提供静态数据,这可能需要很长时间才能初始化。在这种情况下,通常多次初始化不是问题。

    不要使用Cache来维护全局变量。