论坛首页 Java企业应用论坛

oscache 避免使用cacelupdate的原因

浏览 1873 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-11-19   最后修改:2011-11-19
oscache 使用一个状态对象控制缓存更新的过程
其对象共有四个状态 1: 未赋值状态,2 正在更新状态 3 更新完成状态 4 取消更新状态
多线程操作时就是操作这个对象的几个状态
下面代码是oscache官方推荐的使用方法:
* // ---------------------------------------------------------------
 * // Typical use with fail over
 * // ---------------------------------------------------------------
 * String myKey = "myKey";
 * String myValue;
 * int myRefreshPeriod = 1000;
 * try {
 *     // Get from the cache
 *     myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);
 * } catch (NeedsRefreshException nre) {
 *     try {
 *         // Get the value (probably by calling an EJB)
 *         myValue = "This is the content retrieved.";
 *         // Store in the cache
 *         admin.putInCache(myKey, myValue);
 *     } catch (Exception ex) {
 *         // We have the current content if we want fail-over.
 *         myValue = (String) nre.getCacheContent();
 *         // It is essential that cancelUpdate is called if the
 *         // cached content is not rebuilt
 *         admin.cancelUpdate(myKey);
 *     }
 * }

等待的线程栈:
"http-92-50" - Thread t@80
   java.lang.Thread.State: WAITING
	at java.lang.Object.wait(Native Method)
	- waiting on <15be4b4> (a com.opensymphony.oscache.base.EntryUpdateState)
	at java.lang.Object.wait(Object.java:485)
	at com.opensymphony.oscache.base.Cache.getFromCache(Cache.java:278)
	at com.opensymphony.oscache.base.Cache.getFromCache(Cache.java:221)
	at com.opensymphony.oscache.general.GeneralCacheAdministrator.getFromCache(GeneralCacheAdministrator.java:151)


上述代码的admin.cancelUpdate(key); 发生线程阻塞的情况的状态:
  如果同时多个线程对一个key发生访问,第一个线程得到锁后发现为空(状态为1)抛出nre异常并释放锁在catch里去更新数据,第二个线程进入由于发现别一个线程在更新(状态为2),于是waiting.其它线程则处于监视状态直到第二个线程释放状态对象 ,如果第一个线程更新时发生错误,于是cancelUpdate 状态改为(状态4),并释放锁通知第二个线程,它得到锁后发现状态是4则执行iscancel判断后的操作,操作状态改为2,释放锁后,第三个线程时来发现状态为2,于是等待,但这时也没有别的线程在执行更新对象操作了,自己也拿着锁,别人也进不来了,于是此线程一直会处于waiting状态,随着程序的长时间运行其它也取此key的监视线程会一直增加,浪费线程资源,严重时会导致内存溢出

我的解决办法改为admin.put(key,null);  第二个线程会将状态设为3,由于value为null,第三个线程取时会发现状态对象为1,会执行更新缓存操作,不会使第三个线程处于等待状态
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics