我是同步化的新手。我知道当我尝试使用多线程时,在将内容添加到列表中时可能会遇到问题。例如,使用以下代码:
import java.util.ArrayList;
class MySafeList extends ArrayList<Double>{
static ArrayList<Double> mySafeList;
public boolean add(Double d){
mySafeList.add(d);
return true;
}
public int size(){
return mySafeList.size();
}
public Double get(int i){
return mySafeList.get(i);
}
static boolean stressTest(int n, int m){
Thread threads[] = new Thread[n];
try{
for(int i=0; i<n; i++){
threads[i] = new Thread(new ThreadTest(1));
threads[i].start();
for(int j=0; j<m;j++){
Double d = new Double((double) j);
mySafeList.add(d);
}
}
return true;
}catch(Exception e){
return false;
}
}
public static void main(String[] args) {
MySafeList safeList = new MySafeList();
stressTest(2,4);
}
}
我想将同步原语添加到add ()
方法中,是否需要同步读取列表而不修改列表的方法(size ()
和get ()
)? 如有必要,如何同步这些原语并验证MySafeList
是否可用于n
和m
的任何值?
答案 0 :(得分:2)
如果要同步列表,请使用synchronizedList
:
List<Double> mySafeList = Collections.synchronizedList(new ArrayList<>());
请注意,迭代不会同步。
或者,如果您想要不同步的读取访问,但以降低写入速度为代价,请使用CopyOnWriteArrayList
:
List<Double> mySafeList = new CopyOnWriteArrayList<>();
答案 1 :(得分:1)
如果在其他线程正在读取列表时有代码可以修改列表,那么是的,您需要进行同步-以便在读取列表时不会对其进行修改。
最简单的方法是将“已同步”添加到“添加”,“获取”和“大小”方法中。
人们可能会质疑“大小”是否需要,但是我认为,在这种情况下,至少在您在此处编写时,忽略同步几乎不会带来任何好处。
一个不相关的观点:为什么您的“添加”调用返回一个硬连接的“真实”值(使返回无效)而不是列表中“添加”的值?如果您不需要知道是否实际添加了项目,则将其设为void方法。