2013-10-27 76 views
0
一個地圖

我已經看到了這本書的Java 7次的配方更新,並同時遍歷一個地圖驗證碼:更新(和遍歷)在Java中

ConcurrentMap<Integer,String> concurrentMap = new ConcurrentHashMap<Integer, String>(); 
for (int i =0;i < 1000;i++) { 
    startUpdateThread(i, concurrentMap); 
} 
try { 
    Thread.sleep(1000); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
for (Map.Entry<Integer, String> entry : concurrentMap.entrySet()) { 
    System.out.println("Key :"+entry.getKey()+" Value:"+entry.getValue()); 
} 

而且方法如下更新地圖:

private void startUpdateThread(int i, final ConcurrentMap<Integer, String> concurrentMap) { 
    Thread thread = new Thread(new Runnable() { 
     public void run() { 
      while (!Thread.interrupted()) { 
       int randomInt = random.nextInt(20); 
       concurrentMap.put(randomInt, UUID.randomUUID().toString()); 
      } 
} }); 
    thread.setName("Update Thread "+i); 
    updateThreads.add(thread); 
    thread.start(); 
} 

我試過了,只是一個HashMap而不是ConcurrentHasMap,結果是一樣的(用Java VisualVM監控)。有誰知道爲什麼?

感謝, 奧古斯丁

更新:一些有趣的問題:

  1. 如果HashMap具有恆定的容量,下面的操作有什麼可以安全地進行?
    • 兩個線程更新HashMap中的值。
    • 兩個線程在HashMap中更新值,而第三個線程正在讀取HashMap。
  2. 如果我想要更新地圖的速度,在只有4個處理器的計算機中有超過4個線程是否合理?
+0

你是什麼意思「用Java VisualVM監控」? –

+1

當你插入隨機的東西,我不明白你如何得出結論是相同的? – fvu

+0

那你有什麼問題?如果結果相同,會出現什麼問題?那麼你的期望是什麼? –

回答

1

下面的代碼會給你一個不同的結果。你的代碼不會崩潰的原因是20個整數的小隨機區間。因此,您的地圖會立即充滿,然後它的密鑰集不會被修改。我將隨機時間間隔更改爲10000,並增加了睡眠時間,所以現在它在程序運行期間不斷更新,並且崩潰了HashMap。它適用於ConcurrentHashMap,它可以迭代正在修改的數據。

public class Test { 
    static List<Thread> threadList = new ArrayList<>(); 

    public static void main(String[] args) throws InterruptedException { 
     Map<Integer,String> map = new HashMap<>(); 
     for (int i =0;i < 1000;i++) { 
      startUpdateThread(i, map); 
     } 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     for (Map.Entry<Integer, String> entry : map.entrySet()) { 
      System.out.println("Key :"+entry.getKey()+" Value:"+entry.getValue()); 
     } 

     for (Thread thread : threadList) { 
      thread.interrupt(); 
     } 
    } 

    private static void startUpdateThread(int i, final Map<Integer, String> concurrentMap) { 
     Thread thread = new Thread(new Runnable() { 
      public void run() { 
       Random random = new Random(); 
       while (true) { 
        int randomInt = random.nextInt(10000); 
        concurrentMap.put(randomInt, UUID.randomUUID().toString()); 
        try { 
         Thread.sleep(100); 
        } catch (InterruptedException e) { 
         return; 
        } 
       } 
      } }); 

     threadList.add(thread); 

     thread.setName("Update Thread " + i); 
     thread.start(); 
    } 
} 
2

ConcurrentHashMap允許多線程訪問,而不是HashMap哪個沒有。

從多個線程同時調用HashMap#put可能會破壞您的地圖。 ConcurrentHashMap可以處理這些情景並緩解競爭狀況。

至於你的測試特別是,你的地圖只有20個鍵,這意味着它會得到相對較快的速度。 hashmap的弱點在於當你需要擴展存儲區空間並同時放入另一個條目時。嘗試增加Integer.MAX_VALUE的密鑰數量,您將有更高的機會看到它突破。