【问题标题】:simple multithreading program crashing?简单的多线程程序崩溃?
【发布时间】:2015-10-25 00:10:51
【问题描述】:

当我运行它时,我有这个下面的程序,它崩溃了。看起来在运行时有一些问题。我无法理解出了什么问题?谁能解释一下?

public static void main(String[] args) {
    final ArrayList<Object> holder = new ArrayList<>();
    final Runnable runnable = new Runnable() {
        public void run() {
            for (int i = 1; i <= 1000000; i++) {
                holder.add(new Object());
            }

        }
    };

    new Thread(runnable).start();
    new Thread(runnable).start();
    new Thread(runnable).start();
}

这是错误消息,但为什么我收到 ArrayIndexOutOfBoundsException。谁能解释一下?

Exception in thread "Thread-5" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 244

【问题讨论】:

  • “崩溃”是什么意思?你在输出中有一些例外吗?您的 JVM 是否会因报告而崩溃?或者它只是停止了?
  • 是的,我刚刚添加了错误消息.. 之前忘记添加了。

标签: java multithreading runnable


【解决方案1】:

您有多个线程添加到 ArrayList。但是,添加不是线程安全的操作

请注意,此实现不同步。如果多个线程同时访问一个 ArrayList 实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。 (结构修改是添加或删除一个或多个元素,或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。)

http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

【讨论】:

  • 谢谢 Eric,我还用运行时收到的错误消息更新了我的问题。另外,我可以在这里使用什么数据结构来代替 ArrayList?
  • 现在肯定有想法了。我的ArrayIndexOutOfBoundsException 异常呢?为什么会出现这种情况,我该如何解决?
  • 因为If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally,每个线程对ArrayList的当前大小都有自己的想法。一个线程认为“它足够大”,另一个线程中断它并改变了 Array List 的内部状态,然后第一个线程恢复。请注意,对于任何给定的运行,您可能会或可能不会收到此错误。鉴于你的循环又长又紧,你很可能会这样做。不过,它不可能总是在同一点。
【解决方案2】:

您收到此错误是因为多个线程尝试访问同一个列表。例如,如果线程 1 访问列表索引 20,同时线程 2 访问列表索引 20,则会导致问题。有一个简单的解决方案来解决这个问题:

public static void main(String[] args) {
    final Runnable runnable = new Runnable() {
        public void run() {
        final ArrayList<Object> holder = new ArrayList<>();
            for (int i = 1; i <= 1000000; i++) {
                holder.add(new Object());
            }

        }
    };

    new Thread(runnable).start();
    new Thread(runnable).start();
    new Thread(runnable).start();
}

我简单地将列表放在run()-Method 中,这样每个线程都有自己的列表。这样它应该可以工作。

【讨论】:

  • Re,这样它应该可以工作。如果 OP 没有告诉我们它应该做什么,你怎么能说它是否有效做什么?
  • hmmm 如果多个线程试图访问同一个列表,那么为什么我们会得到那个异常,仍然无法理解。
  • 另外,如果我在 ArrayList 上使用Collections.synchronizedList,那么这个错误会自动消失而不进行任何其他更改?
猜你喜欢
  • 2015-05-29
  • 2016-07-09
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多