Java LinkedList多线程在Runnable中创建单独的实例

Java LinkedList多线程在Runnable中创建单独的实例,java,multithreading,linked-list,Java,Multithreading,Linked List,说明我的问题的代码: 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().availab

说明我的问题的代码:

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);
            }
        }
    }
}

我期望{1,2,3,4,5}被删除两次,每个线程删除一次。但是,removeNumbers Runnable似乎共享相同的LocalNumber链接列表。为什么会发生这种情况?我的理解是,我创建了两个单独的localnumbers实例,每个removeNumbers都有一个可运行的实例。

您将对同一LinkedList的引用传递到两个构造函数调用中,因此每个localnumbers都指向同一个列表。这就是为什么两者都从同一个列表中删除,因为您实际上没有复制它

您将希望按照以下思路做一些事情:

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));
}

忽必烈是正确的。如果希望每个RemoveNumber实例在其自己的列表上运行,则必须制作副本。因此,removeNumbers构造函数将创建列表的副本以进行处理。为了更好/更安全,您应该通过集合传递一份不可修改的番石榴列表或一份不可修改的列表。

对。RemoveNumber的两个实例都引用了列表中的同一个实例。+1将复制责任交给构造函数,并传入不可变的内容是个好主意。为什么传入不可变的内容会使它更安全?一个删除程序在将传递的列表发送给下一个删除程序之前更新它不会有风险。一般来说,在处理并发时,不变性是一种方法,因为它可以防止任何并发修改的可能性。
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));
}
String[] numbersarray = {"one", "two", "three", "four", "five"};
String[] numbersarray2 = new String[numbersarray.length];
System.arraycopy(numbersarray, 0, numbersarray2, 0, numbersarray.length);