DWR bug致使CPU 飙高的原因分析
程序员文章站
2022-05-13 11:20:13
...
项目代码使用了DWR组件来进行异步调用,采用的DWR版本为3.0,但最近WebLogic经常发生线程STUCK,经过分析WebLogic的日志,发现了如下信息:
从堆栈上分析师
我们再来分析一下这个方法的源码
问题解决,当然有其他类似的地方还需要修改。
现在来分析一下原因:java中常用的HashSet、ArrayList、HashMap都是线程不安全的,如果多条线程访问他们,而且多于一条的线程试图修改它们,则可能出错。我们遇到的情况就是属于多线程死锁。一般的解决方案有:
1.使用ConcrrentHashMap替代HashMap
2.对象的操作使用同步关键词synchronized
3.得到线程安全的集合
<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());
推荐阅读