Java 仅在周期线程处理变量后才使用该变量

Java 仅在周期线程处理变量后才使用该变量,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我有一个定期运行的线程。线程从数据库中清除并更新数据的哈希映射 假设线程在午夜每24小时运行一次。午夜时,缓存被清除,然后使用数据库中的数据进行更新。在更新过程中,如何仅在线程完成处理后访问此缓存?当然,我可以确保缓存不是空的。然而,还有其他方法可以做到这一点吗 我知道这个问题有点模糊。我正在寻找资源来做我自己的研究和调查 使用标志canGet=true 在更新数据库中的数据之前,请将此标志设为false 现在清除地图并加载它 这与您建议的方式类似,只是变量仅在更新完成时更新,一旦更新完成,请将

我有一个定期运行的线程。线程从数据库中清除并更新数据的哈希映射

假设线程在午夜每24小时运行一次。午夜时,缓存被清除,然后使用数据库中的数据进行更新。在更新过程中,如何仅在线程完成处理后访问此缓存?当然,我可以确保缓存不是空的。然而,还有其他方法可以做到这一点吗


我知道这个问题有点模糊。我正在寻找资源来做我自己的研究和调查

使用标志canGet=true 在更新数据库中的数据之前,请将此标志设为false 现在清除地图并加载它 这与您建议的方式类似,只是变量仅在更新完成时更新,一旦更新完成,请将标志设置为true

从映射中获取数据时,请检查该标志,如果该标志可用,请从映射中获取值


注意:将此标志设置为易变的

缓存线程:每24小时一次

主线程:检查地图是否已填充的线程

有很多方法。最简单的方法是使用低级通信工具(如单个对象上的wait和notify)和标志变量在这两个线程之间建立通信。其中,主线程将等待标志为false,并且一旦设置了标志,缓存线程将通知主线程

其他复杂的方法包括使用循环载波/相位器。使用CyclicBarrier,您可以为两个线程提供一个barrier对象,初始方为2,因此当两个线程调用Wait方法时,主线程将继续,主线程也将重置屏障,以便在第二天使用它

mainThread{
    //some code

      barrier.await();

    //barrier.reset
    //required processing on map

}
cacheThread{
    //Fill map
      barrier.await();

}
假设线程在午夜每24小时运行一次。午夜时,缓存被清除,然后使用数据库中的数据进行更新。在更新过程中,如何仅在线程完成处理后访问此缓存

这是一个非常常见的模式,有很多答案。我倾向于从不清除缓存,而是用新缓存替换缓存

 private volatile Map<?, ?> cacheMap = new HashMap<>();
 ...
 private void updateCache() {
    Map<?, ?> newCacheMap = new HashMap<>();
    // ... fill out the newCacheMap somehow
    // once it is filled out then you can replace the one in use
    this.cacheMap = newCacheMap;
 }
private volatile Map cacheMap=new HashMap();
...
私有void updateCache(){
Map newCacheMap=newhashmap();
//…以某种方式填写新的缓存映射
//填完后,您可以更换正在使用的
this.cacheMap=newCacheMap;
}
请务必注意
volatile
字段,以确保线程在运行时看到完全发布的缓存


如果缓存在内存中太大,无法拥有两个副本(旧的和新的),那么我建议您切换到使用
ConcurrentHashMap
,并为每个元素添加超时时间。然后可以动态更新缓存映射。后台线程将向其添加新元素,并动态删除旧元素。或者,它可以运行缓存中的条目,并通过将它们重新放到地图中来实时刷新它们。

更新后,您希望缓存在下一个午夜之前可用,还是只需要一段时间?如果是前者,为什么不将其设置为某个公共可用的位置(例如具有getter的字段)?任何人都可以从那个地方读取,只要变量不为null,他们就应该使用它。当然也有线程问题,但这本身就是一个完整的问题。在我提供的这个示例中,它将一直持续到下一个午夜。根据你的例子,我不是必须存储在一个变量中,然后在某个时候重写变量吗?本质上,我想做的是在更新发生之前避免与该变量的交互如果交互只是“存储引用,然后使用该本地引用进行任何您需要的操作”,那么为什么您会关心是否有人使用它?换句话说:如果有人在晚上11:58正确地获取了以前的版本,与在计算新缓存时在上午12:01“错误地”获取同一版本有什么不同?