Java 多线程 int 操作做得正确

2024-04-26

这里的代码是一个更大项目的工作原型,但只是为了展示这个想法。 我需要对 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()));
               }
            }

现在它工作得很好,但我不确定它是否是线程安全的 并将按预期工作,我还需要保护循环吗?


错误出现在你的第一个for loop:

for (Thread j : jobs) {
    j.start();
}

Calling start在一系列线程上并不能保证它们都将按照启动时的相同顺序执行。有些线程在执行之前可能会经历轻微的延迟,而其他线程可能会立即执行。

为了确保它们按顺序执行,您必须等待每个任务结束才能开始下一个:

for (Thread j : jobs) {
    j.start();
    // Wait for `j` to die before starting the next thread
    j.join();
}

但无论如何,在您提供的示例中,多线程实际上并不是必需的,因为所有操作都是串行完成的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 多线程 int 操作做得正确 的相关文章

随机推荐