如果标记的方法@Cacheable
需要 10 分钟才能完成,并且两个线程 t1,t2 访问该方法。
t1 在时间 0 访问(缓存方法现在第一次运行) t2 在时间 t1+5mins 访问
这是否意味着 t2 将在大约 5 分钟内不会访问数据,因为 t1 已经开始@Cacheable
操作并且它将在 5 分钟内完成(因为它已经运行了 5 分钟),还是@Cacheable
t2 会调用一个新的调用?
如果标记的方法@Cacheable
需要 10 分钟才能完成,并且两个线程 t1,t2 访问该方法。
t1 在时间 0 访问(缓存方法现在第一次运行) t2 在时间 t1+5mins 访问
这是否意味着 t2 将在大约 5 分钟内不会访问数据,因为 t1 已经开始@Cacheable
操作并且它将在 5 分钟内完成(因为它已经运行了 5 分钟),还是@Cacheable
t2 会调用一个新的调用?
如果第一次执行的结果没有被缓存,第二次调用将继续。
您应该了解,@Cacheable
它以缓存的内容为中心(而不是特别是线程的执行上下文 [嗯,有点;缓存仍然需要是线程安全的])。在执行方法时,首先检查缓存以查看键是否存在:如果 t1 需要一段时间才能完成,则其结果将不会被缓存,因此,将继续并发执行而不考虑 t1 的执行
@Cacheable 上没有阻塞。
但是您可以在缓存实现中使用阻塞缓存策略。First query found miss 有责任重建缓存。其他查询等到缓存重建。
ReadWriteLock
. 见net.sf.ehcache.constructs.blocking.BlockingCache
。从Spring 4.3开始,您可以通过添加 sync = true 标志来获得所需的阻塞行为:
@Cacheable(value="cacheName", key="{#keyField1, #keyField2}", sync = true)
正如巨人解释的那样,在方法调用之前检查缓存。因此,如果该项目不在缓存中(如在 t1 + 5 分钟时的情况),则线程 t2 也会发生方法调用。
@Cacheable 注释上没有“阻塞”。t2 将调用该方法,就好像存在缓存未命中一样,因此 t2 也需要 10 分钟才能完成相同的方法。