Ehcache is an open-source, standards-based cache for boosting performance, offloading your database, and simplifying scalability. As a robust, proven, and full-featured solution, it is today’s most widely used Java-based cache. You can use Ehcache as a general-purpose cache or a second-level cache for Hibernate.
Here let me explaing how to use Ehcache with a simple mutithreading program.Lets start with dependencies required,Below are the depdendecies required to use Ehcache.
Configuration XML :
Let me brieflly explain about attributes of Cache tag
User Model Class :
CachedUserManager :
CachedUserManager will intract with cache and do CRUD operations on cache.
UserEhcacheDemo :
Here is the Demo code to add user objects into cache.This demo will explaing how to add User object to cache and making current thread to sleep, so that idle time of user objects reachs to timeToIdleSeconds(specified in xml) hence objects status will changed to expire and removed from cache.
Above program will have mutiple outputs,Here is one among them
In the Demo program,we have two threads adding 4 users to respective cache.After adding users,trying to retrieving users from cache.While retrieving, threads to going to sleep.Sleep time is randomly calculated as mentioned in the program.If you remember we kept idle time to 1 and 2 mins in respective cache configuration.So if thread sleep for more then 1 min with out reading elements then such elements will expire and removed from cache.
In the above output, users like user4 not exist in cache1 and user3,user4 not exists in cache2.It mean idle time reached for these users,so expired.
You can download source from GitHub.
Here let me explaing how to use Ehcache with a simple mutithreading program.Lets start with dependencies required,Below are the depdendecies required to use Ehcache.
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.5.6</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.5.6</version> </dependency> |
Configuration XML :
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <diskStore path="java.io.tmpdir"/> <cache name="cache1" maxEntriesLocalHeap="1000" maxEntriesLocalDisk="10000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="60" timeToLiveSeconds="300" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> <persistence strategy="localTempSwap"/> </cache> <cache name="cache2" maxEntriesLocalHeap="1000" maxEntriesLocalDisk="10000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="120" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> <persistence strategy="localTempSwap"/> </cache> </ehcache> |
Let me brieflly explain about attributes of Cache tag
- maxEntriesLocalHeap : Maximum no of elements allowed in memory.
- maxEntriesLocalDisk : Once Heap is full,then element overflow to disk memory.So this is maximum no of elements allowed in Disk.
- eternal : Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired.
- diskSpoolBufferSizeMB : This is the size to allocate the DiskStore for a spool buffer. Writes are made
to this area and then asynchronously written to disk. The default size is 30MB.
- timeToIdleSeconds : Element will expire if idle time reachs to timeToIdleSeconds(in seconds).
- timeToLiveSeconds : Element will expire if life of the element reachs to timeToIdleSeconds(in seconds).
- memoryStoreEvictionPolicy : Policy would be enforced upon reaching the maxEntriesLocalHeap limit. Default policy is Least Recently Used (specified as LRU). Other policies available - First In First Out (specified as FIFO) and Less Frequently Used (specified as LFU)
- transactionalMode : To enable an ehcache as transactions, set the transactionalMode.
- diskStore : If heap memory is full,then elements overflow to disk.Diskstore is the path of disk directory.
User Model Class :
public class User implements Serializable{ private Integer userid; private String username; private String password; private String role; private Integer tenantid; public User(Integer userid, String username, String password, String role, Integer tenantid) { this.userid = userid; this.username = username; this.password = password; this.role = role; this.tenantid = tenantid; } //setters & getters } |
CachedUserManager :
CachedUserManager will intract with cache and do CRUD operations on cache.
public class CachedUserManager<K extends Integer, V extends User> { private final Cache cache; public CachedUserManager(Cache cache) { this.cache = cache; } public void add(K k, V v) { cache.put(new Element(k, v)); } public V getValue(K k) { return (V) cache.get(k).getObjectValue(); } public boolean keyExist(K k) { return cache.get(k) == null ? false : true; } public void deleteElement(K k) { if (cache.get(k) != null) { cache.remove(k); } } public Cache getCache() { return cache; } } |
UserEhcacheDemo :
Here is the Demo code to add user objects into cache.This demo will explaing how to add User object to cache and making current thread to sleep, so that idle time of user objects reachs to timeToIdleSeconds(specified in xml) hence objects status will changed to expire and removed from cache.
public class UserEhcacheDemo { public static final String CACHE_1 = "cache1"; public static final String CACHE_2 = "cache2"; public static void main(String[] args) { CacheManager cacheManager = buildCacheManager(); Cache cache1 = getCache1(cacheManager); Cache cache2 = getCache2(cacheManager); final CachedUserManager cachedUserManager1 = new CachedUserManager<Integer, User>(cache1); final CachedUserManager cachedUserManager2 = new CachedUserManager<Integer, User>(cache2); int noOfThreads = 2; ExecutorService execService = Executors.newFixedThreadPool(noOfThreads); execService.submit(new Runnable() { String threadName = "thread_1"; @Override public void run() { //adding some users to cache1 addUsersToCache(cachedUserManager1,threadName); //retrieve users from cache1 Integer i = new Integer(1); while(i<5) { //any random value between 1 to 45 sec int sleepTime = getRandomSleepTime(1000, 45000); System.out.println(threadName +" will sleep during "+sleepTime+" milliseconds"); try { Thread.currentThread().sleep(sleepTime); }catch (InterruptedException e) { //do nothing } boolean exist = cachedUserManager1.keyExist(i); System.out.println("user"+i+ (exist?" exist":" not exist")+ " in cache1 with "+threadName); i++; } } }); execService.submit(new Runnable() { String threadName = "thread_2"; @Override public void run() { //adding some users to cache2 addUsersToCache(cachedUserManager2,threadName); //retrieve users from cache1 Integer i = new Integer(1); while(i<5) { //any random value between 30 to 60 sec int sleepTime = getRandomSleepTime(30000, 60000); System.out.println(threadName +" will sleep during "+sleepTime+" milliseconds"); try { Thread.currentThread().sleep(sleepTime); }catch (InterruptedException e) { //do nothing } boolean exist = cachedUserManager2.keyExist(i); System.out.println("user"+i+ (exist?" exist ":" not exist ")+ "in cache2 with "+threadName); i++; } } }); } public static Cache getCache1(CacheManager cacheManager) { return cacheManager.getCache(CACHE_1); } public static Cache getCache2(CacheManager cacheManager) { return cacheManager.getCache(CACHE_2); } public static CacheManager buildCacheManager() { InputStream is = UserEhcacheDemo.class.getClassLoader().getResourceAsStream("com/ehcache/userCache.xml"); return CacheManager.create(is); } private static void addUsersToCache(CachedUserManager cachedUserManager,String threadName) { Integer i = new Integer(1); while(i<5){ cachedUserManager.add(i, new User(i, "user" + i, "password" + i, "role" + i, i)); System.out.println("Added user"+ i + " to "+ cachedUserManager.getCache().getName() + " using " + threadName); i++; } } private static int getRandomSleepTime(int min, int max){ return min + (int)(Math.random() * ((max - min) + 1)); } } |
Above program will have mutiple outputs,Here is one among them
Added user1 to cache2 using thread_2 Added user2 to cache2 using thread_2 Added user3 to cache2 using thread_2 Added user4 to cache2 using thread_2 thread_2 will sleep during 37461 milliseconds Added user1 to cache1 using thread_1 Added user2 to cache1 using thread_1 Added user3 to cache1 using thread_1 Added user4 to cache1 using thread_1 thread_1 will sleep during 11195 milliseconds user1 exist in cache1 with thread_1 thread_1 will sleep during 12607 milliseconds user2 exist in cache1 with thread_1 thread_1 will sleep during 16771 milliseconds user1 exist in cache2 with thread_2 thread_2 will sleep during 44240 milliseconds user3 exist in cache1 with thread_1 thread_1 will sleep during 10718 milliseconds user4 exist in cache1 with thread_1 user2 exist in cache2 with thread_2 thread_2 will sleep during 56851 milliseconds user3 not exist in cache2 with thread_2 thread_2 will sleep during 41211 milliseconds user4 not exist in cache2 with thread_2 |
In the Demo program,we have two threads adding 4 users to respective cache.After adding users,trying to retrieving users from cache.While retrieving, threads to going to sleep.Sleep time is randomly calculated as mentioned in the program.If you remember we kept idle time to 1 and 2 mins in respective cache configuration.So if thread sleep for more then 1 min with out reading elements then such elements will expire and removed from cache.
In the above output, users like user4 not exist in cache1 and user3,user4 not exists in cache2.It mean idle time reached for these users,so expired.
You can download source from GitHub.