`
ultrang
  • 浏览: 57798 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

DWR bug致使CPU 飙高的原因分析

阅读更多
项目代码使用了DWR组件来进行异步调用,采用的DWR版本为3.0,但最近WebLogic经常发生线程STUCK,经过分析WebLogic的日志,发现了如下信息:
<2015-10-29 上午09时25分44秒 GMT+08:00> <Error> <WebLogicServer> <BEA-000337> <[STUCK] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)' has been busy for "652" seconds working on the request "Workmanager: default, Version: 0, Scheduled=true, Started=true, Started time: 652387 ms 
", which is more than the configured time (StuckThreadMaxTime) of "600" seconds in "server-failure-trigger". Stack trace: 
java.util.HashMap.put(HashMap.java:508) 
java.util.HashSet.add(HashSet.java:217) 
org.directwebremoting.impl.DefaultScriptSessionManager.associateScriptSessionAndPage(DefaultScriptSessionManager.java:242) 
org.directwebremoting.impl.DefaultScriptSessionManager.getScriptSession(DefaultScriptSessionManager.java:125) 
org.directwebremoting.impl.DefaultWebContext.checkPageInformation(DefaultWebContext.java:87) 
org.directwebremoting.dwrp.BaseCallHandler.handle(BaseCallHandler.java:97) 
org.directwebremoting.servlet.UrlProcessor.handle(UrlProcessor.java:120) 
org.directwebremoting.servlet.DwrServlet.doPost(DwrServlet.java:141)

从堆栈上分析师
org.directwebremoting.impl.DefaultScriptSessionManager
出了问题,查看了这个类里面的所有Map都是
new ConcurrentHashMap();
类型的。到底是什么原因呢?
我们再来分析一下这个方法的源码
 protected void associateScriptSessionAndPage(DefaultScriptSession scriptSession, String page)
  {
    if (page == null)
    {
      return;
    }

    String normalizedPage = this.pageNormalizer.normalizePage(page);

    Set pageSessions = (Set)this.pageSessionMap.get(normalizedPage);
    if (pageSessions == null)
    {
      pageSessions = new HashSet();
      Set prev = (Set)this.pageSessionMap.putIfAbsent(normalizedPage, pageSessions);
      if (prev != null)
      {
        pageSessions = prev;
      }
    }

    pageSessions.add(scriptSession);
    scriptSession.setAttribute("org.directwebremoting.ScriptSession.Page", normalizedPage);
  }
我们发现pageSessions没有进行同步操作,所以我们的修改方案是:
synchronized (pageSessions) {
      pageSessions.add(scriptSession);
      scriptSession.setAttribute("comtop.org.directwebremoting.ScriptSession.Page", normalizedPage);
    }


    问题解决,当然有其他类似的地方还需要修改。


    现在来分析一下原因:java中常用的HashSet、ArrayList、HashMap都是线程不安全的,如果多条线程访问他们,而且多于一条的线程试图修改它们,则可能出错。我们遇到的情况就是属于多线程死锁。一般的解决方案有:
   1.使用ConcrrentHashMap替代HashMap
   2.对象的操作使用同步关键词synchronized
   3.得到线程安全的集合
  
Collection c = Collections.synchronizedCollection(new ArrayList());
        List l = Collections.synchronizedList(new ArrayList());
        Set s = Collections.synchronizedSet(new HashSet());
        Map m = Collections.synchronizedMap(new HashMap());
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics