[英]LinkedList multithreading creating separate instances in Runnable
Code that illustrates my problem: 说明我的问题的代码:
public class Linkedlisttest {
public static void main(String[] args) {
Linkedlisttest test = new Linkedlisttest();
test.go(args);
}
public void go(String[] args) {
int cpus = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor tpe = new ThreadPoolExecutor(cpus, cpus * 2, 1L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
String numbersarray[] = {"one", "two", "three", "four", "five"};
LinkedList<String> numbers = new LinkedList(Arrays.asList(numbersarray));
for (int index = 0; index < 2; index++) {
tpe.execute(new removeNumbers(numbers, index));
}
}
class removeNumbers implements Runnable {
LinkedList<String> localnumbers;
int index;
public removeNumbers(LinkedList<String> localnumbers, int index) {
this.localnumbers = localnumbers;
this.index = index;
}
@Override
public void run() {
System.out.println(localnumbers.size() + " Thread#: " + index);
while (localnumbers.size() > 0) {
System.out.println(localnumbers.removeFirst() + " Thread#: " + index);
}
}
}
}
and the output (which varies somewhat in which thread removes what element): 和输出(在哪个线程中删除哪个元素时有所不同):
5 Thread#: 0
5 Thread#: 1
one Thread#: 0
three Thread#: 0
four Thread#: 0
five Thread#: 0
two Thread#: 1
I'm expecting {"one", "two", "three", "four", "five"}
to get removed twice, once by each thread. 我期望{"one", "two", "three", "four", "five"}
被删除两次,每个线程一次。 However, it seems like the removeNumbers
Runnables are sharing the same localnumbers
LinkedList. 但是,似乎removeNumbers
Runnables共享相同的localnumbers
LinkedList。 Why does this happen? 为什么会这样? My understanding is that I've created two separate instances of localnumbers
, one in each removeNumbers
Runnable. 我的理解是,我创建了两个单独的localnumbers
实例,每个removeNumbers
Runnable中一个。
You're passing a reference to the same LinkedList<String>
into both constructor calls, so each localnumbers
is pointing to the same List
. 您要在两个构造函数调用中传递对相同LinkedList<String>
的引用,因此每个localnumbers
都指向相同的List
。 That's why both are removing from the same List
, because you haven't actually copied it. 这就是为什么两者都从同一List
中删除的原因,因为您实际上尚未复制它。
You will want to do something along the lines of: 您将需要执行以下操作:
LinkedList<String> numbers = new LinkedList(Arrays.asList(numbersarray));
for (int index = 0; index < 2; index++) {
LinkedList<String> numbersCopy = new LinkedList<String>(numbers);
tpe.execute(new removeNumbers(numbersCopy, index));
}
There are more efficient ways to make these copies. 有更有效的方法来制作这些副本。 Note that even two calls to Arrays.asList() using the same array will not be enough to truly create copies, since that method returns a List
backed by the array. 请注意,即使使用同一数组对Arrays.asList()的两次调用也不足以真正创建副本,因为该方法返回的是由数组支持的List
。 You will need to create copies of the List
as in the loop above, or else use System.arraycopy() to copy the array at the beginning: 您将需要像上面的循环一样创建List
副本,或者使用System.arraycopy()在开头复制数组:
String[] numbersarray = {"one", "two", "three", "four", "five"};
String[] numbersarray2 = new String[numbersarray.length];
System.arraycopy(numbersarray, 0, numbersarray2, 0, numbersarray.length);
Kublai is correct. 忽必烈是对的。 If you want each removeNumbers instance to operate on it's own list you must make copies. 如果希望每个removeNumbers实例在其自己的列表上运行,则必须进行复制。 So you removeNumbers constructor would create a copy of the list for processing. 因此,您removeNumbers构造函数将创建列表的副本以进行处理。 To make this even better / safer you should pass in an ImmutableList (Guava) or an unmodifiable List (via Collections). 为了使它更好/更安全,您应该传递一个ImmutableList(Guava)或一个不可修改的List(通过Collections)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.