Caching is very important when you want to improve your Java application performance
In My Project there was some performance issue during show huge date in screen. In that case
i have improve my java application performance by written own Cache Utility class, Which is below
public class UtilCache
{
private UtilCache(String cacheName, int sizeLimit, int maxInMemory, long expireTimeMillis, boolean useSoftReference, boolean useFileSystemStore, String propName, String... propNames) {
this.name = cacheName;
this.sizeLimit = sizeLimit;
this.maxInMemory = maxInMemory;
this.expireTimeNanos = TimeUnit.NANOSECONDS.convert(expireTimeMillis, TimeUnit.MILLISECONDS);
this.useSoftReference = useSoftReference;
this.useFileSystemStore = useFileSystemStore;
setPropertiesParams(propName);
setPropertiesParams(propNames);
int maxMemSize = this.maxInMemory;
if (maxMemSize == 0) maxMemSize = sizeLimit;
if (maxMemSize == 0) {
memoryTable = new ConcurrentHashMap<Object, CacheLine<V>>();
} else {
memoryTable = new Builder<Object, CacheLine<V>>()
.maximumWeightedCapacity(maxMemSize)
.listener(this)
.build();
}
if (this.useFileSystemStore) {
// create the manager the first time it is needed
jdbmMgr = fileManagers.get(fileStore);
if (jdbmMgr == null) {
Debug.logImportant("Creating file system cache store for cache with name: " + cacheName, module);
try {
String ofbizHome = System.getProperty("ofbiz.home");
if (ofbizHome == null) {
Debug.logError("No ofbiz.home property set in environment", module);
} else {
jdbmMgr = new JdbmRecordManager(ofbizHome + "/" + fileStore);
}
} catch (IOException e) {
Debug.logError(e, "Error creating file system cache store for cache with name: " + cacheName, module);
}
fileManagers.putIfAbsent(fileStore, jdbmMgr);
}
jdbmMgr = fileManagers.get(fileStore);
if (jdbmMgr != null) {
try {
this.fileTable = HTree.createInstance(jdbmMgr);
jdbmMgr.setNamedObject(cacheName, this.fileTable.getRecid());
jdbmMgr.commit();
} catch (IOException e) {
Debug.logError(e, module);
}
}
}
}
private static String getNextDefaultIndex(String cacheName) {
AtomicInteger curInd = defaultIndices.get(cacheName);
if (curInd == null) {
defaultIndices.putIfAbsent(cacheName, new AtomicInteger(0));
curInd = defaultIndices.get(cacheName);
}
int i = curInd.getAndIncrement();
return i == 0 ? "" : Integer.toString(i);
}
public static String getPropertyParam(ResourceBundle res, String[] propNames, String parameter) {
try {
for (String propName: propNames) {
if(res.containsKey(propName+ '.' + parameter)) {
try {
return res.getString(propName + '.' + parameter);
} catch (MissingResourceException e) {}
}
}
// don't need this, just return null
//if (value == null) {
// throw new MissingResourceException("Can't find resource for bundle", res.getClass().getName(), Arrays.asList(propNames) + "." + parameter);
//}
} catch (Exception e) {
Debug.logWarning(e, "Error getting " + parameter + " value from cache.properties file for propNames: " + propNames, module);
}
return null;
}
protected void setPropertiesParams(String cacheName) {
setPropertiesParams(new String[] {cacheName});
}
public void setPropertiesParams(String[] propNames) {
ResourceBundle res = ResourceBundle.getBundle("cache");
if (res != null) {
String value = getPropertyParam(res, propNames, "maxSize");
if (UtilValidate.isNotEmpty(value)) {
this.sizeLimit = Integer.parseInt(value);
}
value = getPropertyParam(res, propNames, "maxInMemory");
if (UtilValidate.isNotEmpty(value)) {
this.maxInMemory = Integer.parseInt(value);
}
value = getPropertyParam(res, propNames, "expireTime");
if (UtilValidate.isNotEmpty(value)) {
this.expireTimeNanos = TimeUnit.NANOSECONDS.convert(Long.parseLong(value), TimeUnit.MILLISECONDS);
}
value = getPropertyParam(res, propNames, "useSoftReference");
if (value != null) {
useSoftReference = "true".equals(value);
}
value = getPropertyParam(res, propNames, "useFileSystemStore");
if (value != null) {
useFileSystemStore = "true".equals(value);
}
value = getPropertyParam(res, new String[0], "cache.file.store");
if (value != null) {
fileStore = value;
}
}
}
private Object fromKey(Object key) {
return key == null ? ObjectType.NULL : key;
}
@SuppressWarnings("unchecked")
private K toKey(Object key) {
return key == ObjectType.NULL ? null : (K) key;
}
private void addAllFileTableKeys(Set<Object> keys) throws IOException {
FastIterator<Object> iter = fileTable.keys();
Object key = null;
while ((key = iter.next()) != null) {
keys.add(key);
}
}
public Object getCacheLineTable() {
throw new UnsupportedOperationException();
}
public boolean isEmpty() {
if (fileTable != null) {
try {
synchronized (this) {
return fileTable.keys().next() == null;
}
} catch (IOException e) {
Debug.logError(e, module);
return false;
}
} else {
return memoryTable.isEmpty();
}
}
/** Puts or loads the passed element into the cache
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @param value The value of the element
*/
public V put(K key, V value) {
return putInternal(key, value, expireTimeNanos);
}
public V putIfAbsent(K key, V value) {
return putIfAbsentInternal(key, value, expireTimeNanos);
}
CacheLine<V> createSoftRefCacheLine(final Object key, V value, long loadTimeNanos, long expireTimeNanos) {
return tryRegister(loadTimeNanos, new SoftRefCacheLine<V>(value, loadTimeNanos, expireTimeNanos) {
@Override
CacheLine<V> changeLine(boolean useSoftReference, long expireTimeNanos) {
if (useSoftReference) {
if (differentExpireTime(expireTimeNanos)) {
return this;
} else {
return createSoftRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
}
} else {
return createHardRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
}
}
@Override
void remove() {
removeInternal(key, this);
}
});
}
CacheLine<V> createHardRefCacheLine(final Object key, V value, long loadTimeNanos, long expireTimeNanos) {
return tryRegister(loadTimeNanos, new HardRefCacheLine<V>(value, loadTimeNanos, expireTimeNanos) {
@Override
CacheLine<V> changeLine(boolean useSoftReference, long expireTimeNanos) {
if (useSoftReference) {
return createSoftRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
} else {
if (differentExpireTime(expireTimeNanos)) {
return this;
} else {
return createHardRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
}
}
}
@Override
void remove() {
removeInternal(key, this);
}
});
}
private CacheLine<V> tryRegister(long loadTimeNanos, CacheLine<V> line) {
if (loadTimeNanos > 0) {
ExecutionPool.addPulse(line);
}
return line;
}
private CacheLine<V> createCacheLine(K key, V value, long expireTimeNanos) {
long loadTimeNanos = expireTimeNanos > 0 ? System.nanoTime() : 0;
if (useSoftReference) {
return createSoftRefCacheLine(key, value, loadTimeNanos, expireTimeNanos);
} else {
return createHardRefCacheLine(key, value, loadTimeNanos, expireTimeNanos);
}
}
private V cancel(CacheLine<V> line) {
// FIXME: this is a race condition, the item could expire
// between the time it is replaced, and it is cancelled
V oldValue = line.getValue();
ExecutionPool.removePulse(line);
line.cancel();
return oldValue;
}
/** Puts or loads the passed element into the cache
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @param value The value of the element
* @param expireTimeMillis how long to keep this key in the cache
*/
public V put(K key, V value, long expireTimeMillis) {
return putInternal(key, value, TimeUnit.NANOSECONDS.convert(expireTimeMillis, TimeUnit.MILLISECONDS));
}
public V putIfAbsent(K key, V value, long expireTimeMillis) {
return putIfAbsentInternal(key, value, TimeUnit.NANOSECONDS.convert(expireTimeMillis, TimeUnit.MILLISECONDS));
}
V putInternal(K key, V value, long expireTimeNanos) {
Object nulledKey = fromKey(key);
CacheLine<V> oldCacheLine = memoryTable.put(nulledKey, createCacheLine(key, value, expireTimeNanos));
V oldValue = oldCacheLine == null ? null : cancel(oldCacheLine);
if (fileTable != null) {
try {
synchronized (this) {
if (oldValue == null) oldValue = fileTable.get(nulledKey);
fileTable.put(nulledKey, value);
jdbmMgr.commit();
}
} catch (IOException e) {
Debug.logError(e, module);
}
}
if (oldValue == null) {
noteAddition(key, value);
return null;
} else {
noteUpdate(key, value, oldValue);
return oldValue;
}
}
}
In My Project there was some performance issue during show huge date in screen. In that case
i have improve my java application performance by written own Cache Utility class, Which is below
public class UtilCache
{
private UtilCache(String cacheName, int sizeLimit, int maxInMemory, long expireTimeMillis, boolean useSoftReference, boolean useFileSystemStore, String propName, String... propNames) {
this.name = cacheName;
this.sizeLimit = sizeLimit;
this.maxInMemory = maxInMemory;
this.expireTimeNanos = TimeUnit.NANOSECONDS.convert(expireTimeMillis, TimeUnit.MILLISECONDS);
this.useSoftReference = useSoftReference;
this.useFileSystemStore = useFileSystemStore;
setPropertiesParams(propName);
setPropertiesParams(propNames);
int maxMemSize = this.maxInMemory;
if (maxMemSize == 0) maxMemSize = sizeLimit;
if (maxMemSize == 0) {
memoryTable = new ConcurrentHashMap<Object, CacheLine<V>>();
} else {
memoryTable = new Builder<Object, CacheLine<V>>()
.maximumWeightedCapacity(maxMemSize)
.listener(this)
.build();
}
if (this.useFileSystemStore) {
// create the manager the first time it is needed
jdbmMgr = fileManagers.get(fileStore);
if (jdbmMgr == null) {
Debug.logImportant("Creating file system cache store for cache with name: " + cacheName, module);
try {
String ofbizHome = System.getProperty("ofbiz.home");
if (ofbizHome == null) {
Debug.logError("No ofbiz.home property set in environment", module);
} else {
jdbmMgr = new JdbmRecordManager(ofbizHome + "/" + fileStore);
}
} catch (IOException e) {
Debug.logError(e, "Error creating file system cache store for cache with name: " + cacheName, module);
}
fileManagers.putIfAbsent(fileStore, jdbmMgr);
}
jdbmMgr = fileManagers.get(fileStore);
if (jdbmMgr != null) {
try {
this.fileTable = HTree.createInstance(jdbmMgr);
jdbmMgr.setNamedObject(cacheName, this.fileTable.getRecid());
jdbmMgr.commit();
} catch (IOException e) {
Debug.logError(e, module);
}
}
}
}
private static String getNextDefaultIndex(String cacheName) {
AtomicInteger curInd = defaultIndices.get(cacheName);
if (curInd == null) {
defaultIndices.putIfAbsent(cacheName, new AtomicInteger(0));
curInd = defaultIndices.get(cacheName);
}
int i = curInd.getAndIncrement();
return i == 0 ? "" : Integer.toString(i);
}
public static String getPropertyParam(ResourceBundle res, String[] propNames, String parameter) {
try {
for (String propName: propNames) {
if(res.containsKey(propName+ '.' + parameter)) {
try {
return res.getString(propName + '.' + parameter);
} catch (MissingResourceException e) {}
}
}
// don't need this, just return null
//if (value == null) {
// throw new MissingResourceException("Can't find resource for bundle", res.getClass().getName(), Arrays.asList(propNames) + "." + parameter);
//}
} catch (Exception e) {
Debug.logWarning(e, "Error getting " + parameter + " value from cache.properties file for propNames: " + propNames, module);
}
return null;
}
protected void setPropertiesParams(String cacheName) {
setPropertiesParams(new String[] {cacheName});
}
public void setPropertiesParams(String[] propNames) {
ResourceBundle res = ResourceBundle.getBundle("cache");
if (res != null) {
String value = getPropertyParam(res, propNames, "maxSize");
if (UtilValidate.isNotEmpty(value)) {
this.sizeLimit = Integer.parseInt(value);
}
value = getPropertyParam(res, propNames, "maxInMemory");
if (UtilValidate.isNotEmpty(value)) {
this.maxInMemory = Integer.parseInt(value);
}
value = getPropertyParam(res, propNames, "expireTime");
if (UtilValidate.isNotEmpty(value)) {
this.expireTimeNanos = TimeUnit.NANOSECONDS.convert(Long.parseLong(value), TimeUnit.MILLISECONDS);
}
value = getPropertyParam(res, propNames, "useSoftReference");
if (value != null) {
useSoftReference = "true".equals(value);
}
value = getPropertyParam(res, propNames, "useFileSystemStore");
if (value != null) {
useFileSystemStore = "true".equals(value);
}
value = getPropertyParam(res, new String[0], "cache.file.store");
if (value != null) {
fileStore = value;
}
}
}
private Object fromKey(Object key) {
return key == null ? ObjectType.NULL : key;
}
@SuppressWarnings("unchecked")
private K toKey(Object key) {
return key == ObjectType.NULL ? null : (K) key;
}
private void addAllFileTableKeys(Set<Object> keys) throws IOException {
FastIterator<Object> iter = fileTable.keys();
Object key = null;
while ((key = iter.next()) != null) {
keys.add(key);
}
}
public Object getCacheLineTable() {
throw new UnsupportedOperationException();
}
public boolean isEmpty() {
if (fileTable != null) {
try {
synchronized (this) {
return fileTable.keys().next() == null;
}
} catch (IOException e) {
Debug.logError(e, module);
return false;
}
} else {
return memoryTable.isEmpty();
}
}
/** Puts or loads the passed element into the cache
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @param value The value of the element
*/
public V put(K key, V value) {
return putInternal(key, value, expireTimeNanos);
}
public V putIfAbsent(K key, V value) {
return putIfAbsentInternal(key, value, expireTimeNanos);
}
CacheLine<V> createSoftRefCacheLine(final Object key, V value, long loadTimeNanos, long expireTimeNanos) {
return tryRegister(loadTimeNanos, new SoftRefCacheLine<V>(value, loadTimeNanos, expireTimeNanos) {
@Override
CacheLine<V> changeLine(boolean useSoftReference, long expireTimeNanos) {
if (useSoftReference) {
if (differentExpireTime(expireTimeNanos)) {
return this;
} else {
return createSoftRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
}
} else {
return createHardRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
}
}
@Override
void remove() {
removeInternal(key, this);
}
});
}
CacheLine<V> createHardRefCacheLine(final Object key, V value, long loadTimeNanos, long expireTimeNanos) {
return tryRegister(loadTimeNanos, new HardRefCacheLine<V>(value, loadTimeNanos, expireTimeNanos) {
@Override
CacheLine<V> changeLine(boolean useSoftReference, long expireTimeNanos) {
if (useSoftReference) {
return createSoftRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
} else {
if (differentExpireTime(expireTimeNanos)) {
return this;
} else {
return createHardRefCacheLine(key, getValue(), loadTimeNanos, expireTimeNanos);
}
}
}
@Override
void remove() {
removeInternal(key, this);
}
});
}
private CacheLine<V> tryRegister(long loadTimeNanos, CacheLine<V> line) {
if (loadTimeNanos > 0) {
ExecutionPool.addPulse(line);
}
return line;
}
private CacheLine<V> createCacheLine(K key, V value, long expireTimeNanos) {
long loadTimeNanos = expireTimeNanos > 0 ? System.nanoTime() : 0;
if (useSoftReference) {
return createSoftRefCacheLine(key, value, loadTimeNanos, expireTimeNanos);
} else {
return createHardRefCacheLine(key, value, loadTimeNanos, expireTimeNanos);
}
}
private V cancel(CacheLine<V> line) {
// FIXME: this is a race condition, the item could expire
// between the time it is replaced, and it is cancelled
V oldValue = line.getValue();
ExecutionPool.removePulse(line);
line.cancel();
return oldValue;
}
/** Puts or loads the passed element into the cache
* @param key The key for the element, used to reference it in the hastables and LRU linked list
* @param value The value of the element
* @param expireTimeMillis how long to keep this key in the cache
*/
public V put(K key, V value, long expireTimeMillis) {
return putInternal(key, value, TimeUnit.NANOSECONDS.convert(expireTimeMillis, TimeUnit.MILLISECONDS));
}
public V putIfAbsent(K key, V value, long expireTimeMillis) {
return putIfAbsentInternal(key, value, TimeUnit.NANOSECONDS.convert(expireTimeMillis, TimeUnit.MILLISECONDS));
}
V putInternal(K key, V value, long expireTimeNanos) {
Object nulledKey = fromKey(key);
CacheLine<V> oldCacheLine = memoryTable.put(nulledKey, createCacheLine(key, value, expireTimeNanos));
V oldValue = oldCacheLine == null ? null : cancel(oldCacheLine);
if (fileTable != null) {
try {
synchronized (this) {
if (oldValue == null) oldValue = fileTable.get(nulledKey);
fileTable.put(nulledKey, value);
jdbmMgr.commit();
}
} catch (IOException e) {
Debug.logError(e, module);
}
}
if (oldValue == null) {
noteAddition(key, value);
return null;
} else {
noteUpdate(key, value, oldValue);
return oldValue;
}
}
}