2017-02-03 49 views
0

我在下面的代碼嘗試。雖然用一個線程修改ArrayList並用另一個線程迭代它,但它拋出ConcurrentModificationException

public class IteratorFailFastTest { 

    private List<Integer> list = new ArrayList<>(); 

    public IteratorFailFastTest() { 
     for (int i = 0; i < 10; i++) { 
      list.add(i); 
     } 
    } 

    public void runUpdateThread() { 
     Thread thread2 = new Thread(new Runnable() { 

      public void run() { 
       for (int i = 10; i < 20; i++) { 
        list.add(i); 

       } 
      } 
     }); 

     thread2.start(); 
    } 


    public void runIteratorThread() { 
     Thread thread1 = new Thread(new Runnable() { 

      public void run() { 
       ListIterator<Integer> iterator = list.listIterator(); 

       while (iterator.hasNext()) { 
       Integer number = iterator.next(); 
       System.out.println(number); 
       } 

      } 
     }); 

     thread1.start(); 
    } 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     IteratorFailFastTest tester = new IteratorFailFastTest(); 

     tester.runIteratorThread(); 
     tester.runUpdateThread(); 
    } 

} 

它有時拋出ConcurrentModificationException並且有時會成功運行。

我不明白的是,因爲有2個不同的方法,每個包含一個線程。他們將一一執行。當一個線程完成修改列表時,線程2將開始迭代。

我也提到這個鏈接(Why no ConcurrentModificationException when one thread iterating (using Iterator) and other thread modifying same copy of non-thread-safe ArrayList),但它是不同的情況。

那麼,它爲什麼拋出這個異常?是因爲線程嗎?

有人可以解釋一下嗎?

+0

請不要鏈接到代碼/文章。編輯您的問題以包含實際的代碼片段。 – Bohemian

+0

@Bohemian:我編輯了這篇文章。 –

+0

應該沒有CME:迭代器被創建但沒有被使用 – Bohemian

回答

0

您正在啓動兩個線程,然後不再進行同步。

有時,兩個線程將同時運行,您將獲得CME。其他時候,第一個線程將在第二個線程實際開始執行之前完成。在那種情況下不會得到CME。

你得到這種變化的原因可能歸結於你的系統上的負載。或者它可能只是由於線程調度器是非確定性的事實。

與創建/啓動線程的開銷相比,您的線程實際上只執行少量工作。因此,其中一人可以很快從其run()方法返回,這並不奇怪。

+0

如果我將它們稱爲「Thread obj = new Thread()」,那麼情況就是這樣。 obj.start(); Thread obj2 = new Thread(); obj2.start();」但這些是兩種不同的方法。他們將被逐一調用。他們不是嗎? –

+0

是的。他們是。但仔細閱讀javadoc的'start()'。它們不保證在start()調用返回給調用者的時候,子線程將*運行。事實上,兩個'start()'調用使用不同的方法是無關緊要的。 –

相關問題