【发布时间】:2016-07-28 18:41:08
【问题描述】:
我在 main 方法中有一个列表,我想编写两个线程来使用这个列表。有时我会在同步块中捕获 IndexOutOfBoundsException(当线程调用 remove 方法时)。
主要方法:
public class PC {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
new Costumer("c1", strings).start();
new Costumer("c2", strings).start();
new Producer("p1", strings).start();
new Producer("p2", strings).start();
new Producer("p3", strings).start();
new Producer("p4", strings).start();
}
}
消费类:
class Costumer extends Thread {
List<String> strings;
public Costumer(String n, List<String> strings) {
super(n);
this.strings = strings;
}
@Override
public void run() {
while (true) {
synchronized (strings) {
try {
if (strings.isEmpty()) {
strings.wait();
}
strings.remove(0); // <- where exception is thrown
} catch (InterruptedException ex) {
}
}
}
}
}
生产者类:
class Producer extends Thread {
List<String> strings;
public Producer(String n, List<String> strings) {
super(n);
this.strings = strings;
}
@Override
public void run() {
while (true) {
synchronized (strings) {
strings.add(String.valueOf(Math.random() * 1000));
if (strings.size() == 1) {
strings.notify();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
}
堆栈跟踪:
Exception in thread "c2" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.remove(Unknown Source)
at Costumer.run(PC.java:40)
【问题讨论】:
-
这绝对不是您使用此代码时遇到的错误。你认为
Arrays.asList会返回什么?你读过它的 javadoc 吗? -
我还有另一个线程来生成字符串并将它们放入列表中。我总结了一下。在主代码中我有新的 Arraylist。
-
这就是为什么你应该测试你自己的代码,如果它真的重现了问题。顺便说一句:我不认为这段代码可以重现这个问题,即使你已经修复了你的列表初始化。因此,还要发布通知您的线程的代码(因为这也可能重新填充该列表)。
-
生产者将字符串添加到空列表时,我调用通知方法。
-
我仍然认为您的代码无法重现此问题。如果你有一个生产者,那么它会通知一个客户,这不会造成任何问题。那么你能创建一个minimal reproducible example吗?
标签: java multithreading arraylist concurrency synchronization