java如何让线程只添加到一个带有同步
我一直在尝试做一些简单的事情,比如让两个线程添加到一个arraylist,但无论出于什么原因,我都无法让它工作。我有同步方法和使用集合。已同步列表,但仍显示它正在打印两个单独的数组。为了更好地理解运行两个线程访问一个arrayList,我编写了一个简短的程序。如果有人能说明我犯了什么错误,我将不胜感激
这是主课
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunThreads {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
int[] numbers1 = {0, 2, 4, 6, 8};
int[] numbers2 = {1, 3, 5, 7, 9};
executor.execute(new ThreadToRun(numbers1));
executor.execute(new ThreadToRun(numbers2));
executor.shutdown();
}
}
以下是Theadatorun类:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ThreadToRun implements Runnable {
List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
private int[] array;
public ThreadToRun(int[] array) {
this.array = array;
}
public void run() {
list = adder(array);
for(int i=0; i<list.size(); i++){
System.out.print(list.get(i)+"("+i+")"); //print out the element at i and the index
} //to see if there are two arrays with the same index
}
public List<Integer> adder(int [] a){
List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
for (int array : a) {
synchronized(list){
list.add(array);
}
}
return list;
}
}
# 1 楼答案
在这里,您将创建两个“theadatorun”实例,每个实例将实例化list的一个新实例(如下所述)
此外,在加法器方法中,您正在执行以下操作:
这将再次创建一个新列表,并覆盖实例中的现有列表
可能的解决方案:
# 2 楼答案
您正在为每个“ThreadToRun”实例创建新的ArrayList。所以它们不是相同的列表
你需要在跑步者之间分享一份名单
# 3 楼答案
list
是ThreadToRun
的实例成员。每次创建ThreadToRun
时,它都会将其list
设置为一个新的ArrayList
。这意味着每个线程都有自己的列表。这两个线程没有共享一个列表有很多方法可以让它共享一个列表,但其中一些是不推荐的(单例模式),还有一些是非常讨厌的(
static
类成员)。最干净的方法可能是将列表作为构造函数的参数。然后RunThreads
将创建列表并将其传递给两个线程的构造函数:在{}中:
现在,您的线程将使用相同的列表
还有一个问题我一开始没注意到,因为你在你的
adder
中使用了一个局部变量list
,这让我很困惑。看起来adder
创建了第二个列表,您也将其称为list
,我认为它将被添加到第一个列表中。但由于这是一个局部变量,它不会在线程之间共享;因此synchronized
在错误的地方。我不确定你的意图是什么。如果希望adder
实际添加到主list
,那么不能使用名为list
的局部变量,因为这样会隐藏列表。但是如果你想要adder
仅仅创建一个新列表,并且让run
将新列表添加到主列表中,那么synchronized
必须位于run
中,围绕着添加到主列表中的代码。不幸的是,我不太确定你想做什么# 4 楼答案
我建议你做两件事:
list = adder(array);
的方法。因此,它将始终替换ArrayList的内容。列表中的任何早期数据都将被方法返回的新列表替换李>相反,你可以用下面的方法
list.add(adder(array));
static
。这样,你的两个线程都会很常见,它们会进入同一个列表李># 5 楼答案
您创建了同步集合的两个实例(在
ThreadToRun
的第6行中)ThreadToRun
的每个实例一个。您必须在所有线程之间共享同一实例。有几种方法可以做到这一点。例如,这可以通过使列表保持静态(我不喜欢这样)或通过构造函数将实例传递给类来实现