java - 如何等待数据缓存更新,同时不影响其他缓存调用

标签 java multithreading caching

我有一个中央数据缓存,它由在 SQL 数据库上运行查询的多个线程进行更新。还有一种机制可以检查数据缓存中最后一个特定项目 (Mydata) 何时被检索,如果达到某个时间阈值(即,如果数据尚未获取),则关闭相应的线程。在过去 30 分钟内被检索)。该机制的存在是为了尝试减少对数据库的需求并最大限度地减少长时间运行的查询。

还有许多线程从缓存获取数据,因此问题是,即使特定项目 (Mydata) 不再更新,它也可能被某个线程请求某个点。发生这种情况时,会检查相关线程是否正在运行,如果没有,则会再次启动,如下所示...

private static HashMap<String, MyData> dataMap = new HashMap<>(10);

public static MyData getMyData(String identifier) {
  if(!MyThreadManager.getInstance().isRunning(identifier)) {
     LOG.info("Thread with identifier={} possibly stopped, restarting.", identifier);
     MyThreadManager.getInstance().startThread(identifier);
  }
  MyData myData= null;
  if(dataMap.containsKey(identifier)) {
     myData= dataMap.get(identifier);
  } else {
     LOG.debug("No data found in dataMap for identifier={}, thread possibly terminated. Restarting.", identifier);
  }
  return myData;
}

...该机制本身工作正常,但我面临这样的风险:当运行 dataMap.get(identifier) 时,它可能仍然只包含 myData 的“过时”版本 (因为重新启动的线程可能仍在处理中)。但是我想保证返回的数据已经更新。为此,我可以在重新启动线程一秒钟后添加一个 sleep 计时器,这应该足以让线程在 dataMap.get(identifier) 之前更新 dataMap 中的数据 已运行。

if(!MyThreadManager.getInstance().isRunning(identifier)) {
  LOG.info("Thread with identifier={} possibly stopped, restarting.", identifier);
  MyThreadManager.getInstance().startThread(identifier);
  try {
        Thread.sleep(1000L);
    } catch (Exception e) {
        LOG.error(e.getMessage());
    }
}

我在这个实现中遇到的一个大问题是,它可能会对尝试检索信息的任何其他线程产生负面影响。

问题:如何实现线程安全/非锁定方式,以便在线程重新启动时“等待”缓存更新,而不影响使用相同数据缓存的其他线程。

最佳答案

好的,所以进行了一些测试。如果从线程内调用 getMyData 方法...

public class MyRunnable implements Runnable {

  private String identifier = "";

  public MyRunnable(String identifier) {
    this.identifier = identifier;
  }

  @Override
  public void run() {
    MyData myData = MyDataManager.getInstance().getMyData(identifier)
    System.out.println(String.format("Data retrieved : %s", myData.toString()));
  }

}

...然后引入Thread.sleep(1000L);来重新启动数据收集线程不会对任何其他并发线程产生影响。当然,除非添加 synchronized 方法关键字,这会强制一次一个以避免竞争条件。

由于这些请求的起源最终来自 Servlet 容器处理的 HTTP 请求,因此上面的方法可以正常工作。由于 Servlet 允许 JVM 在单独的 Java 线程中处理每个请求。因此,对 getMyData 方法的每次调用都在其自己的线程上,任何“等待”都会影响其他请求。

关于java - 如何等待数据缓存更新,同时不影响其他缓存调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58724525/

相关文章:

c# - 修改DataGridView绑定(bind)的大数据集需要很长时间?

python - ThreadPoolExecutor 中的 ''.join() 占用内存

c# - 使用 Entity Framework 防止缓存的对象最终出现在数据库中

caching - gitlab-runner kubernetes 缓存被忽略

java - 在 IntelliJ IDEA 中,如何创建以当前文件作为参数执行 shell 脚本的键绑定(bind)?

java - 有没有办法在 Wildfly 中禁用自动 JSON PATCH 应用程序

java - 进程运行的线程数大于tomcat maxThreads

java - 使用html转java,如何从坐标中获取街道名称?

java - 检查数组列表中的空字符串

spring - 如何停止 org.springframework.web.client.RestTemplate 缓存响应?