可以多运行几次这个代码就会遇到死循环,请高手分析分析是什么原因导致死循环。import java.util.HashMap;public class TestHashMap {
    private HashMap map = new HashMap();
    private void putData(){
        for(int i=0;i<100000;i++){
            map.put(new Key(i), new Integer(i));
            //map.put("1", "1");
            if(i%100 ==0){
                System.out.println("put i="+i+" thread="+Thread.currentThread().getName());
                //System.out.println("size=" + map.toString());
            }
            reset();
        }
        System.out.println("put end thread="+Thread.currentThread().getName());
    }// end putData
    
    /**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里
     * 重新指定hashmap。
     */
    
    private synchronized void reset(){
        if(map.size() > 1000){
            map.clear();
            map = new HashMap();
        }
    }//end reset
    
    private class Key{
        int v ;
        private Key(int v){
            this.v = v;
        }
        public int hashCode() {//返回相同的hash值
            return 1;
        }
        public boolean equals(Object obj) {//由v值确定
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Key other = (Key) obj;
            if (!getOuterType().equals(other.getOuterType()))
                return false;
            if (v != other.v)
                return false;
            return true;
        }
        private TestCircleHashMap getOuterType() {
            return TestCircleHashMap.this;
        }
    }//end class
    
    public static void main(String[] args) {
        final TestHashMap test = new TestHashMap ();
        for(int i=0;i<2;i++){
            new Thread("Thread_"+i){
                public void run(){
                    test.putData();
                }
            }.start();
        }
    }
}

解决方案 »

  1.   

    TestCircleHashMap 这个类请贴一下
      

  2.   

    改成     private Map map = Collections.synchronizedMap(new HashMap()); 

    map = Collections.synchronizedMap(new HashMap()); 
    因为HashMap不是线程安全的,所以会导致不正确
      

  3.   

    上面的有点错,希望得到为什么会死循环,不是想问怎么解决这个死循环的问题。import java.util.HashMap; public class TestHashMap { 
        private HashMap map = new HashMap(); 
        private void putData(){ 
            for(int i=0;i <100000;i++){ 
                map.put(new Key(i), new Integer(i)); 
                //map.put("1", "1"); 
                if(i%100 ==0){ 
                    System.out.println("put i="+i+" thread="+Thread.currentThread().getName()); 
                    //System.out.println("size=" + map.toString()); 
                } 
                reset(); 
            } 
            System.out.println("put end thread="+Thread.currentThread().getName()); 
        }// end putData 
        
        /**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里 
        * 重新指定hashmap。 
        */ 
        
        private synchronized void reset(){ 
            if(map.size() > 1000){ 
                map.clear(); 
                map = new HashMap(); 
            } 
        }//end reset 
        
        private class Key{ 
            int v ; 
            private Key(int v){ 
                this.v = v; 
            } 
            public int hashCode() {//返回相同的hash值 
                return 1; 
            } 
            public boolean equals(Object obj) {//由v值确定 
                if (this == obj) 
                    return true; 
                if (obj == null) 
                    return false; 
                if (getClass() != obj.getClass()) 
                    return false; 
                Key other = (Key) obj; 
                if (!getOuterType().equals(other.getOuterType())) 
                    return false; 
                if (v != other.v) 
                    return false; 
                return true; 
            } 
            private TestHashMap getOuterType() { 
                return TestHashMap.this; 
            } 
        }//end class 
        
        public static void main(String[] args) { 
            final TestHashMap test = new TestHashMap (); 
            for(int i=0;i <2;i++){ 
                new Thread("Thread_"+i){ 
                    public void run(){ 
                        test.putData(); 
                    } 
                }.start(); 
            } 
        } 
    }
      

  4.   

    HashMap 不是现成安全的,它设计的时候就没有考虑到线程的问题,那么在线程中使用时会出现未知错误
    如:资源抢占等, 
      

  5.   

    我已经说了HashMap不是线程安全的,它在多线程同时put或者remove入元素的时候是不正确的。这个已经是文档中清楚写明白!
      

  6.   

    在HashMap中有一段for (Entry<K,V> e = table[i]; e != null; e = e.next) 在修改的过程中,会由于调整Map的保存会修改e.next,但是由于同步修改,会造成e.next指向错了例如开始情况:
    e1.next = e2;
    e2.next = null;线程1修改,放入eNew1,eNew2
    所以将试图变成e1.next = e2;
    e2.next = eNew1;
    eNew1.next = eNew2;
    eNew2.next = null;
    但是同时线程2也放入内容,但是同时它试图修改放大table的大写以减少同时放在table[i]中的数量
    table[i]
    e.next = e2;
    e2.next = null;table[j]
    eNew2.next = eNew1;
    eNew1.next = null;
    但是两者同时修改,结果导致变成
    eNew2.next = eNew1;
    eNew1.next = eNew2;这样就是一个死循环了。上面只是一种情况,事实由于并发的不确定性,可能还会出现其它问题
    所以你应该同步这个Map
      

  7.   

    你synchronized reset有什么用呢?你要保证的是map.put不被多个线程同时调用,像下面这样,就不会死锁
    private HashMap map = new HashMap(); 
        private  void putData(){ 
            for(int i=0;i <100000;i++){ 
                put(new Key(i), new Integer(i)); 
                //map.put("1", "1"); 
                if(i%100 ==0){ 
                    System.out.println("put i="+i+" thread="+Thread.currentThread().getName()); 
                    //System.out.println("size=" + map.toString()); 
                } 
                reset(); 
            } 
            System.out.println("put end thread="+Thread.currentThread().getName()); 
        }// end putData 
        
        /**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里 
        * 重新指定hashmap。 
        */ 
        
        private void reset(){ 
            if(map.size() > 1000){ 
                map.clear(); 
                map = new HashMap(); 
            } 
        }//end reset 
        
        private synchronized void put(Key k,Integer i){
         map.put(k, i); 
        }