CloudDatastoreCache extends AbstractRemoteCache { @Override public Lock acquireLock(String lockName) { DatastoreLock lock = new DatastoreLock(lockName); lock.lock(); return lock; }  @Override byte[] get(String key); @Override void set(String key, byte[] value); @Override void set(String key, byte[] value, int expireIn); @Override void delete(String key); int deleteExpiredItems(); int deleteExpiredItems(Integer limit); @Override Lock acquireLock(String lockName); @Override CheckResult checkConnection(); final static String CACHE_KIND; final static String CACHE_VALUE_FIELD; final static String CACHE_EXPIRY_FIELD; }
@Test public void testLock() throws InterruptedException { String LOCK_NAME = "test-lock"; int WAIT = 20; List<String> list = Collections.synchronizedList(new ArrayList<>()); Callable<Object> task1 = () -> { Lock lock = cache.acquireLock(LOCK_NAME); Thread.sleep(WAIT); list.add("a1"); Thread.sleep(WAIT); list.add("b1"); Thread.sleep(WAIT); list.add("c1"); lock.unlock(); return null; }; Callable<Object> task2 = () -> { Lock lock = cache.acquireLock(LOCK_NAME); Thread.sleep(WAIT); list.add("a2"); Thread.sleep(WAIT); list.add("b2"); Thread.sleep(WAIT); list.add("c2"); lock.unlock(); return null; }; List<Callable<Object>> tasks = new ArrayList<>(); tasks.add(task1); tasks.add(task2); ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.invokeAll(tasks); String result = String.join(",", list); assertTrue(result.equals("a1,b1,c1,a2,b2,c2") || result.equals("a2,b2,c2,a1,b1,c1")); }