Categories

  • articles

Tags

  • java

I have a application that needs to pull data from the database do some calculations (This takes a second or two) then returns. I have been using Guava’s LoadingCache to do this. The problem came in when a user makes a change to the source data which in effect invalidates the calculation results. Easy solution just invalidate. But what happens if the data is modified during the calculation process. For example you have 2 threads, Thread 1 calls get on the loading cache then during the Loading process in Thread 1, Thread 2 calls invalidate since the underlying data has changed. Is the data invalidated or is the invalid/stale data stored in the cache?

I found that in version 16.0 the stale data is loaded and the invalidate is ignored. Here is how I found this:

public class Test09ThreadsLoadingCache {

static AtomicInteger counter = new AtomicInteger();

public static void main(String[] args) throws ExecutionException {
  final LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder().build(new CacheLoader<Integer, Integer>() {
    @Override
    public Integer load(Integer key) throws Exception {
      System.out.println("Thread 1 : Started the loading Process");
      Thread.sleep(2000);
      try {
        return counter.getAndIncrement();
      } finally {
        System.out.println("Thread 1 : Finished the loading Process");
      }
    }
  });

  Thread th = new Thread(new Runnable() {
    public void run() {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      System.out.println("Thread 2 : Call Invalidate!");
      cache.invalidate(1);
    }
  });

  th.start();
  System.out.println(cache.get(1));
}

As you can see here I have a Loading Cache that increments a AtmoicInteger every time get is called where there is no cached value. So if you call get(1), 0 will be returned. If you call get(1) again value 0 will be returned again. Then if you invalidate(1) and get(1) again you will receive value 1. I have added a delay in the loading process to simulate a long calculating process. The Thread will then invalidate the currently calculating value.

The output for this is: Thread 1 : Started the loading Process Thread 2 : Call Invalidate! Thread 1 : Finished the loading Process Cache Value : 0