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

项目中DWR 3.0版本引发WebLogic线程STUCK问题,经分析日志发现HashMap在多线程环境中未进行同步操作,导致死锁。解决方案包括使用ConcurrentHashMap替代,加synchronized关键字或使用线程安全集合。
摘要由CSDN通过智能技术生成
项目代码使用了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());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值