不用Lock,改用ConcurrentHashMap试试。不过,架构一开始就有问题,在这里一时半会也说不清楚。建议你先看看acegisecurity的HttpSessionIntegrationFilter的原代码,或来参加我们的面对面的技术交流活动。http://www.tianji.com/Event/DetailEvent?eventId=486896&groupId=

解决方案 »

  1.   

    1.不明白为什么要用2个MAP
    //再添加新的用户
    sessionId_user.put(sessionId,user);
    loginName_sessionId.put(user.getLoginname(),sessionId);2.另外,读锁可以不要的.
    readLock.lock();
    readLock.unlock();
      

  2.   

    回LS,2个MAP是为了避免遍历MAP读锁还是有必要的,避免脏读
      

  3.   

    到了这里,就想知道两件事情一:为什么调用addUser(HttpSession session,TUser user)后会发生死锁,而改用addUser(String sessionId,TUser user)却很正常.二:LS有大哥讲这个设计有问题,请谈谈你们的设计思路.提高提高.谢谢
      

  4.   

    不知道你理解的session和application各是一个什么概念?
    j2ee里为什么要设计有这两种作用域?public class OnlineUser implements HttpSessionListener {    private static final Map<String, String> onlineUsers = Collections.synchronizedMap(new HashMap<String, String>());    /**
         * 返回当前登陆用户数
         */
        public static int size() {
            return onlineUsers.size();
        }    /**
         * 根据会话ID获得当前用户对象
         */
        public static String getUserName(String sessionId) {
            return onlineUsers.get(sessionId);
        }
        /**
         * 新增登陆用户
         */
        public static void addUser(String sessionId, User user) {
            onlineUsers.put(sessionId, user.getUsername());
        }    /**
         * 根据会话ID检查该用户是否登陆
         */
        public static boolean containsUserByLoginName(String loginName) {
            return onlineUsers.containsValue(loginName);
        }    /**
         * 根据会话ID检查该用户是否登陆
         */
        public static boolean containsUserBySessionID(String sessionId) {
            return onlineUsers.containsKey(sessionId);
        }    /**
         * 根据会话ID删除用户
         */
        public static void removeUserBySessionId(String sessionId) {
            onlineUsers.remove(sessionId);
        }
        /**
         * 会话创建
         */
        public void sessionCreated(HttpSessionEvent se) {    }    /**
         * 会话结束
         */
        public void sessionDestroyed(HttpSessionEvent se) {
            onlineUsers.remove(se.getSession().getId());
        }    /**
         * 返回登陆用户Iterator
         */
        public static Iterator userIterator() {
            return onlineUsers.values().iterator();
        }
    }
      

  5.   

    dreamover(梦醒了〖http://hellfire.cn〗) 你的意思是user对象就不应该存放到map中,而仅保存一个用户名?那么需要使用用户对象的时候,如何处理?每次从ORM中来吗,是这个意思吗?
      

  6.   

    addUser(HttpSession session,TUser user),等同于用一个线程访问另一个线程的资源,你可能需要先分析web容器对session变量的保护机制,如果采用threadlocal进行保护的~~,你的问题应该很容易解释。不管怎么说,我总觉得你这个类设计并不是很好的说。
      

  7.   

    你的HttpSession使用可能有问题吧,你的方法怎么都没有异常捕获的?建议在这个addUser加一个异常捕获。
      

  8.   

    回zhwh(韩信) 没有异常发生另外,我考虑了下,其实dreamover(梦醒了〖http://hellfire.cn〗)和我的代码的区别就在于是否要将用户对象放内存,我是放的,而dreamover(梦醒了〖http://hellfire.cn〗)只是放用户名称.
    这样就有一个问题,如果踢用户的问题,因为我们的项目是需要踢掉上次该用户的登陆的。
    之所以放用户用户对象到MAP,也是便于处理的考虑.如果改用dreamover(梦醒了〖http://hellfire.cn〗)的代码,那就比较麻烦了.如果没有这样的需求,倒是可以使用dreamover(梦醒了〖http://hellfire.cn〗)的方法.还是期待大家的讨论,因为问题还是没有解决哦.
      

  9.   

    HashMap是线程不安全的,你这种设计应该用HashTable
      

  10.   

    另外,hashtable早就不建议使用实在要同步的MAP 使用包装: Collections.synchronizedMap当然,在这个地方,读写锁更高效.
      

  11.   

    死锁的原因是多线程间缺少通信,建议楼主用wait()与notifyAll()处理下
      

  12.   

    回 tonyyl(没有比事实更真实的了) 读写锁就是多线程的同步机制,原理是独占写,同时读,所以效率一般很高.另外这个代码也是经过项目实践了.所以很是不解.
      

  13.   

    比较赞同:
    addUser(HttpSession session,TUser user),等同于用一个线程访问另一个线程的资源,你可能需要先分析web容器对session变量的保护机制,如果采用threadlocal进行保护的~~,你的问题应该很容易解释。
    同步可以用Synchronous定义同步变量,同步函数,不需要再添加锁对象
      

  14.   

    不管别的,至少这两个同名的方法写得不好,应该是session做参数的调用另一个才更优化呀。
      

  15.   

    回wkj83823(如风) 要是直接用Synchronous的话,效率不敢恭维.而且使用读写锁的思路比较合理自然的,主要是效率问题.idilent(怎么理解怎么说) 说的倒是个值得注意的经验.
      

  16.   

    CSDN看来是没落了.没有办法了,结贴