ArrayList中的异常示例?

时间:2014-07-25 03:26:21

标签: java multithreading collections

我正在使用ArrayList,如果多个线程试图在没有同步的情况下访问同一个列表,我想要一个Exception示例?我在单线程应用程序中完成了这个,如果我们在迭代时从列表中删除一个元素,它会抛出ConcurrentModificationExceptoin,但我想在多线程环境中实现相同的功能。如果有人能给我一个例子,我会非常感激吗?

package com.test2;

public class ThreadTest extends Thread {

    List list = new ArrayList<String>();

    @Override
    public void run() {

        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        list.add("6");
        list.add("7");
        list.add("8");

        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

    }

    public static void main(String[] args) {



        Thread th1 = new ThreadTest();
        Thread th2 = new ThreadTest();
        Thread th3 = new ThreadTest();
        th1.start();
        th2.start();
        th3.start();
        try {
            th1.join();
            th2.join();
            th3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }




    }

}

4 个答案:

答案 0 :(得分:1)

快速回答:

public class Main {

    public static void main(String[] args) throws InterruptedException
    {
        final ArrayList<String> list = new ArrayList<String>();
        list.add("Item 1");
        list.add("Item 2");
        list.add("Item 3");
        list.add("Item 4");

        Thread thread = new Thread(new Runnable()
        {
            @Override
            public void run ()
            {
                for (String s : list)
                {
                    System.out.println(s);
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread.start();

        Thread.sleep(2000);
        list.remove(0);
    }
}

输出:

Item 1
Item 2
Exception in thread "Thread-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at com.akefirad.tests.Main$1.run(Main.java:34)
    at java.lang.Thread.run(Thread.java:745)

注意: 正如@Braj和@DaoWen所说,你正在使用不同的实例。要么使用他们的建议,要么在类的构造函数中传递list变量(ThreadTest)。

答案 1 :(得分:1)

您正在每个线程中访问单独的列表实例。由于每个列表只能由一个线程访问,因此无法获得并发错误。

List list = new ArrayList<String>();

宣告实例字段。因此,每次调用new ThreadTest()都会创建一个新列表。为了使所有ThreadTest个实例使用相同的列表,请尝试创建字段static(即类字段):

static List list = new ArrayList<String>();

至于 如何发生错误,请查看the code for ArrayList's add method

 public boolean add(E e) {
     ensureCapacityInternal(size + 1);  // Increments modCount!!
     elementData[size++] = e;
     return true;
 }

如果两个线程同时调用add,他们可以同时处理elementData[size++] = e语句。 The size field is not declared volatile;因此,两个线程最终可能会写入elementData数组中的相同索引。

即使声明size volatilesize++操作也不是原子。有关size++之类的操作在多线程环境中如何失败的示例,请参阅 How to model a situation, when i++ is corrupted by simultaneously executing threads?

最后,如果您不了解Java上下文中的volatile和原子意味着什么,那么在编写任何多线程代码之前,您确实需要阅读Java中的并发编程。这将是一项值得的投资,因为你可以通过理解这些概念来节省很多麻烦。

答案 2 :(得分:0)

如果我理解你的问题,可以改变这个

List list = new ArrayList<String>();

使用Collections.synchronizedList(List)之类的内容(不使用raw types),

List<String> list = Collections.synchronizedList(new ArrayList<String>());

来自javadoc,

  

返回由指定列表支持的同步(线程安全)列表。为了保证串行访问,必须通过返回的列表完成对后备列表的所有访问。

     

当迭代时,用户必须手动同步返回的列表:

List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
  Iterator i = list.iterator(); // Must be in synchronized block
  while (i.hasNext())
    foo(i.next());
  }
}

答案 3 :(得分:0)

  

它会抛出ConcurrentModificationExceptoin,但我希望在多线程环境中实现相同的目标

     

我问如何在多线程环境中获得异常 - 来自评论

由于您为每个线程创建List的单独副本,因此无法获得此异常。

只需将List设为共享资源,您就会遇到此异常:

示例代码:

public class Main{

    public static void main(String[] args){

        // shared by all the threads.
        final List<String> list = new ArrayList<String>();

        class ThreadTest extends Thread {


            @Override
            public void run() {

                list.add("1");
                list.add("2");
                list.add("3");
                list.add("4");
                list.add("5");
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                list.add("6");
                list.add("7");
                list.add("8");

                Iterator<String> it = list.iterator();
                while (it.hasNext()) {
                    System.out.println(it.next());
                }

            }
        }

        Thread th1 = new ThreadTest();
        Thread th2 = new ThreadTest();
        Thread th3 = new ThreadTest();
        th1.start();
        th2.start();
        th3.start();
        try {
            th1.join();
            th2.join();
            th3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出:

Exception in thread "Thread-2" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at com.test.TestDemo$1ThreadTest.run(TestDemo.java:390)