<2015-10-29 上午09时25分44秒 GMT+08:00><[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());