我正在学习Java多线程。我写了一小段代码,并产生了一些输出,我无法通过understand..please帮助进行一些解释。发布下面的代码。
package com.java.learn;
import java.util.ArrayList;
import java.util.List;
public class ListTestWithMultiThread {
static final List<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
list.add(Integer.valueOf(i));
}
System.out.println("List size at thread 0 : " + list.size());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 101; i <= 200; i++) {
list.add(Integer.valueOf(i));
}
System.out.println("List size at thread 1 : " + list.size());
}
}).start();
}
}不同运行中的一些o/p :线程0: 134的列表大小线程1: 200的列表大小
Exception in thread "Thread-1" List size at thread 0 : 101
java.lang.ArrayIndexOutOfBoundsException: 17
at java.util.ArrayList.add(Unknown Source)
at com.java.learn.ListTestWithMultiThread$2.run(ListTestWithMultiThread.java:25)
at java.lang.Thread.run(Unknown Source)
List size at thread 0 : 106
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 58
at java.util.ArrayList.add(Unknown Source)
at com.java.learn.ListTestWithMultiThread$2.run(ListTestWithMultiThread.java:25)
at java.lang.Thread.run(Unknown Source)发布于 2016-02-20 13:29:25
您正在访问的数据结构( list)不是为并行访问而设计的,而没有对其进行保护(例如通过synchronized)。这最终会破坏数据结构的内部,导致奇怪的行为,就像你得到的异常一样。
这里有两种处理方法:
使用并发data-structure:的
List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
synchronized保护列表:已同步(列表){ list.add(Integer.valueOf(i));}
编辑:既然您要求这样做,那么ArrayList是如何被破坏的呢?ArrayList由一个数组支持,该数组必须在列表增长时调整大小。在这里调整大小意味着分配一个新的、更大的数组,并将旧数组的内容复制到新数组中。下面是实现这一功能的the code部分:
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
...
elementData = Arrays.copyOf(elementData, newCapacity);现在想象一下:线程A开始调整数组的大小,它计算新的容量,并开始复制第4行的数据。但是在它可以将新数组的引用复制到elementData之前,它因为任何原因而停止(这种情况一直都在发生)。现在线程B开始调整数组的大小并完成。然后,它将更多的值插入到列表中,并再次调整数组的大小并完成操作。线程B现在假设列表足够大,可以容纳一个新值,但是在插入新值之前,线程A会唤醒,并用它创建的较小数组的引用覆盖elementData。线程B现在尝试将一个值插入到较小的数组中,并获得一个ArrayIndexOutOfBoundsException。这一切都有点不太可能,但正如你所见,它是可以发生的。
发布于 2016-02-20 13:23:21
您正在从两个不同的线程访问list变量,而没有进行任何同步(锁定)。这将导致未定义的行为。
您可能希望尝试将列表声明替换为以下内容:
static final List list = Collections.synchronizedList(new ArrayList());另一种选择是使用Vector而不是ArrayList。Vector是实现List接口的同步集合。
发布于 2016-02-20 13:40:23
ArrayList不是线程安全的。ArrayList实施由阵列提供支持。存在与ArrayList相关的大小变量。每当我们向ArrayList添加任何元素时,它都会首先确保它的容量,然后再向数组添加元素。未定义数组列表的状态对每个线程可见,因为您正在两个线程之间共享非线程安全实现。https://stackoverflow.com/questions/35519352
复制相似问题