天天看點

ConcurrentModificationException

項目中有一處多線程通路HashTable的地方;一個線程對 HashTable進行周遊,一個線程對它進行增、删操作。項目運作一段時間之後,就時不時的報一個java.util.ConcurrentModificationException 出來,然後線程死翹翹了。

上網查了一下,這個異常的原因是在對HashTable進行周遊時,對HashTable進行了增、删操作。如果是單線程的操作,應該 把增、删操作拿到HastTable外面來;如果是多線程的操作,似乎就要使用多線程同步機制了。

但是,并沒有這麼複雜。我寫了一個測試類,分别測試了兩種周遊和增删HashTable的方法。代碼如下:

package test;

import java.util.Enumeration;

import java.util.Hashtable;

import java.util.Iterator;

import org.junit.Before;

import org.junit.Test;

public class HasttableTest {

 private Hashtable<String, String> table;

 private int i;

 @Before

 public void setUp() throws Exception {

  i = 0;

  table = new Hashtable<String, String>();

  table.put("a", "aa");

  table.put("b", "bb");

  table.put("c", "cc");

 }

 @Test

 public void testEnu() {

  System.out.println("Enumeration 周遊開始");

  Enumeration<String> keys = table.keys();

  while (keys.hasMoreElements()) {

   i++;

   String key = (String) keys.nextElement();

   System.out.println(key + "---" + table.get(key));

   System.out.println("i=" + i);

   if (i == 1) {

    table.put("d", "dd");

    table.remove("b");

   }

  }

  System.out.println("Enumeration 周遊結束");

 public void TestIte() {

  System.out.println("Iterator遍 曆開始");

  Iterator<String> it = table.keySet().iterator();

  while (it.hasNext()) {

   String key = (String) it.next();

    // table.put("d", "dd");

    table.remove("c");

  System.out.println("Iterator 周遊結束");

}

執行的結果是,testEnu()方法能夠正常執行完畢,而TestIte()方法則會跑出異常。

為什麼會這樣?我上網查了一下,準确的答案忘記了,大體上是說,HashTable、Enumeration等是線程安全的,在多線程操作中會自己 進行同步;而Iterator等則是不安全的,如果使用它,就要由程式顯式的進行同步操作。

本文轉自 斯然在天邊 51CTO部落格,原文連結:http://blog.51cto.com/winters1224/798950,如需轉載請自行聯系原作者

繼續閱讀