<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    xylz,imxylz

    關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

       :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評(píng)論 :: 0 Trackbacks

    大家都知道HashMap不是線程安全的,但是大家的理解可能都不是十分準(zhǔn)確。很顯然讀寫同一個(gè)key會(huì)導(dǎo)致不一致大家都能理解,但是如果讀寫一個(gè)不變的對(duì)象會(huì)有問題么?看看下面的代碼就明白了。

     1 import java.util.HashMap;
     2 import java.util.Map;
     3 import java.util.Random;
     4 import java.util.concurrent.ExecutorService;
     5 import java.util.concurrent.Executors;
     6 import java.util.concurrent.TimeUnit;
     7 import java.util.concurrent.atomic.AtomicInteger;
     8 
     9 public class HashMapTest2 {
    10     static void doit() throws Exception{
    11         final int count = 200;
    12         final AtomicInteger checkNum = new AtomicInteger(0);
    13         ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(100);
    14         //
    15         final Map<Long, String> map = new HashMap<Long, String>();
    16         map.put(0L"www.imxylz.cn");
    17         //map.put(1L, "www.imxylz.cn");
    18         for (int j = 0; j < count; j++) {
    19             newFixedThreadPool.submit(new Runnable() {
    20                 public void run() {
    21                     map.put(System.nanoTime()+new Random().nextLong(), "www.imxylz.cn");
    22                     String obj = map.get(0L);
    23                     if (obj == null) {
    24                         checkNum.incrementAndGet();
    25                     }
    26                 }
    27             });
    28         }
    29         newFixedThreadPool.awaitTermination(1, TimeUnit.SECONDS);
    30         newFixedThreadPool.shutdown();
    31         
    32         System.out.println(checkNum.get());
    33     }
    34     
    35     public static void main(String[] args) throws Exception{
    36         for(int i=0;i<10;i++) {
    37             doit();
    38             Thread.sleep(500L);
    39         }
    40     }
    41 }
    42 

    結(jié)果一定會(huì)輸出0么?結(jié)果卻不一定。比如某一次的結(jié)果是:

     

    0
    3
    0
    0
    0
    0
    9
    0
    9
    0

     

    查看了源碼,其實(shí)出現(xiàn)這個(gè)問題是因?yàn)镠ashMap在擴(kuò)容是導(dǎo)致了重新進(jìn)行hash計(jì)算。

    在HashMap中,有下面的源碼:

     
     1     public V get(Object key) {
     2         if (key == null)
     3             return getForNullKey();
     4         int hash = hash(key.hashCode());
     5         for (Entry<K,V> e = table[indexFor(hash, table.length)];
     6              e != null;
     7              e = e.next) {
     8             Object k;
     9             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
    10                 return e.value;
    11         }
    12         return null;
    13     }


    在indexOf中就會(huì)導(dǎo)致計(jì)算有偏移。

    1 static int indexFor(int h, int length) {
    2         return h & (length-1);
    3     }

     

    很顯然在Map的容量(table.length,數(shù)組的大小)有變化時(shí)就會(huì)導(dǎo)致此處計(jì)算偏移變化。這樣每次讀的時(shí)候就不一定能獲取到目標(biāo)索引了。為了證明此猜想,我們改造下,變成以下的代碼。

    final Map<String, String> map = new HashMap<String, String>(10000);

    執(zhí)行多次結(jié)果總是輸出:

     

    0
    0
    0
    0
    0
    0
    0
    0
    0
    0

     

    當(dāng)然了如果只是讀,沒有寫肯定沒有并發(fā)的問題了。改換Hashtable或者ConcurrentHashMap肯定也是沒有問題了。


    這里有一篇完整分析HashMap原理的文章。 __ by xylz 2010.07.20


    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2009-12-18 18:20 imxylz 閱讀(6164) 評(píng)論(2)  編輯  收藏 所屬分類: J2EE技術(shù)

    評(píng)論

    # re: HashMap的讀寫并發(fā) 2009-12-31 11:27 bing
    很有意思,謝謝!  回復(fù)  更多評(píng)論
      

    # re: HashMap的讀寫并發(fā)[未登錄] 2010-07-20 15:38 test
    是hashcode的index變了,而不是hashcode變了,0L的hashcode應(yīng)該會(huì)始終不變的。  回復(fù)  更多評(píng)論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 日本高清免费观看| 久久久久久久久亚洲| 亚洲免费电影网站| aa午夜免费剧场| 亚洲AV无码专区在线电影成人 | 涩涩色中文综合亚洲| 亚洲人成人一区二区三区| 国产免费av片在线播放| 好先生在线观看免费播放| 真实国产乱子伦精品免费| 国产成人AV免费观看| jizz免费在线观看| 国产亚洲视频在线观看| 亚洲另类自拍丝袜第五页| 亚洲人成777在线播放| 亚洲视频中文字幕在线| 亚洲AV天天做在线观看| 国产亚洲美女精品久久久久狼| 亚洲国产成人a精品不卡在线| 国产亚洲福利一区二区免费看| 久久久www成人免费毛片| 免费在线看v网址| 国产成人精品免费视频大全麻豆| 在线观看的免费网站无遮挡| 一级毛片免费观看| 无码国产精品一区二区免费式芒果 | 亚洲AV无码国产剧情| 久久精品国产99国产精品亚洲| 亚洲美女一区二区三区| 亚洲精品在线观看视频| 亚洲黄色在线观看视频| 亚洲白嫩在线观看| 亚洲最大免费视频网| 亚洲成aⅴ人在线观看| 亚洲一级免费视频| 97se亚洲国产综合自在线| 国产精品亚洲片在线va| 亚洲暴爽av人人爽日日碰| 日韩亚洲人成网站| 产传媒61国产免费| 日本道免费精品一区二区|