2017-02-03 43 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()'调用使用不同的方法是无关紧要的。 –

相关问题