簡體   English   中英

用Java更新(和迭代)地圖

[英]Updating (and Iterating) a Map in Java

我已經在Java 7食譜書中看到了以下代碼,可以同時更新和迭代Map:

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. 如果我想加快更新Map的速度,那么在只有4個處理器的計算機中擁有4個以上的線程是否有意義?

ConcurrentHashMap允許多線程訪問,而HashMap則不允許。

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

特別是對於您的測試,您的地圖只有20個鍵,這意味着它將相對較快地充滿。 哈希圖的弱點是當您需要擴展存儲桶空間並同時放置另一個條目時。 嘗試增加Integer.MAX_VALUE的鍵數量,您將有更大的機會看到它被破壞。

下面的代碼將為您提供不同的結果。 您的代碼不會崩潰的原因是一個很小的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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM