这里的代码是一个更大项目的工作原型,但只是为了展示这个想法。
我需要对 int 执行很多操作,对每个 int 执行很多操作。
我决定将所有操作存储在列表中,所有整数都将存储在列表中
每个线程将执行 1 个操作并将在所有列表上运行
但在结果integerList中不断得到错误的数字:
这是示例代码:
import java.util.ArrayList;
import java.util.List;
class ArithmeticA implements ArithmeticManager.ArithmeticAction {
@Override
public int arithmetic(int n) {
return n+1;
}
}
class ArithmeticB implements ArithmeticManager.ArithmeticAction {
@Override
public int arithmetic(int n) {
return n*2;
}
}
public class ArithmeticManager {
private List<Integer> integerList = new Vector<>();
private List<Integer> tempList = new ArrayList<Integer>();
public ArithmeticManager(List<Integer> dataFromUser) {
this.integerList = dataFromUser;
}
private void exec(ArithmeticAction arithmeticAction) {
for (int i : integerList) {
synchronized (tempList) {
tempList.add(arithmeticAction.arithmetic(i));
}
}
integerList = tempList;
}
public List<Integer> invokerActions(List<ArithmeticAction> actions) throws
InterruptedException {
List<Thread> jobs = new ArrayList<Thread>();
for (final ArithmeticAction ac : actions) {
jobs.add(new Thread(() -> exec(ac)));
}
//added start
for (Thread j : jobs) {
j.start();
}
for (Thread j : jobs) {
j.join();
}
return integerList;
}
public interface ArithmeticAction {
int arithmetic(int n);
}
public static void main(String[] args) {
List<ArithmeticManager.ArithmeticAction> actions = new ArrayList();
actions.add(new ArithmeticA());
actions.add(new ArithmeticB());
List<Integer> intData = new ArrayList<>();
intData.add(1);
intData.add(2);
intData.add(3);
intData.add(4);
ArithmeticManager arithmeticManager = new ArithmeticManager(intData);
try {
List<Integer> result = arithmeticManager.invokerActions(actions);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这是结果,看起来像是数字被累积:
integerList = {ArrayList@656} size = 4
0 = {Integer@658} 4
value = 4
1 = {Integer@659} 6
value = 6
2 = {Integer@660} 8
value = 8
3 = {Integer@661} 10
value = 10
UPDATE移动 List 之后 tempList = new ArrayList();到顶级
并添加同步:
for (int i : integerList) {
synchronized (tempList) {
tempList.add(arithmeticAction.arithmetic(i));
}
}
我仍然得到:
Exception in thread "Thread-1" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at ArithmeticManager.exec(ArithmeticManager.java:32)
at ArithmeticManager.lambda$invokerActions$0(ArithmeticManager.java:44)
at java.lang.Thread.run(Thread.java:748)
但是当我将integerList初始化为向量时
private List<Integer> integerList = new Vector<>();
一切正常,但现在我有双重同步,这不好
另外我也不知道用户是否会使用 ArrayList 或向量启动对象类
这样做的正确方法是什么?
UPDATE2我将循环转换为:
for(Iterator<Integer> iterator = integerList.listIterator(); iterator.hasNext();) {
synchronized (tempList) {
tempList.add(arithmeticAction.arithmetic(iterator.next()));
}
}
现在它工作得很好,但我不确定它是否是线程安全的
并将按预期工作,我还需要保护循环吗?