Learn Java Smart Locking With Reentracklock and Loadingcache
Lock your code smartly using ReentrantLock and LoadingCache from the Guava library. What if you want to lock an update-database operation ba...
Lock your code smartly using ReentrantLock and LoadingCache from the Guava library. What if you want to lock an update-database operation base on a given id as a parameter? For example, you have an application that is update-heavy, and multiple requests come all the time. Update request with id parameter 1 and 2 should be fine as they are updating 2 separate records in the database, but what if both requests have id=1 comes at the same time? Then, there might be an issue as we will not know which value will be the final version.
1. Introduction
In this code example, I'll share a code that uses ReentrantLock with LoadingCache. LoadingCache will have String and ReentrantLock as parameters, String is the key.
2. Actual Code
package com.czetsuya.lock; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; public class KeyLock { public final static int THREAD_POOL_SIZE = 10; public static Map<String, Integer> mapOfHashTableObjects = null; private static LoadingCache<String, ReentrantLock> lockCache = CacheBuilder // .newBuilder() // .build(new CacheLoader<String, ReentrantLock>() { @Override public ReentrantLock load(String key) { return new ReentrantLock(); } }); public static void lock(String key) { try { lockCache.getUnchecked(key).tryLock(10, TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } } public static void unlock(String key) { lockCache.getUnchecked(key).unlock(); } public static void main(String args[]) { try { mapOfHashTableObjects = new HashMap<String, Integer>(); new KeyLock().performTest(); System.out.println(mapOfHashTableObjects); } catch (InterruptedException e) { e.printStackTrace(); } } public void updateMap(Integer randomNo) { String strKey = String.valueOf(randomNo); KeyLock.lock(strKey); try { mapOfHashTableObjects.put(strKey, randomNo); } finally { KeyLock.unlock(strKey); } } public void performTest() throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE); for (int j = 0; j < THREAD_POOL_SIZE; j++) { executorService.execute(new Runnable() { @Override public void run() { for (int i = 0; i < 100000; i++) { Integer randomNo = (int) Math.ceil(Math.random() * 50000); updateMap(randomNo); } } }); } executorService.shutdown(); executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.MINUTES); } }
Post a Comment