当前位置: 首页 > 知识库问答 >
问题:

尽管使用同步对集合进行排序,但仍获得并发修改异常

全誉
2023-03-14

我尝试使用线程方法对集合进行排序,其中方法分别调用比较器类

public class ThreadedSort{
   public ThreadedSort(){
       ThreadedIDSort idSort=new ThreadedIDSort();
       ThreadedNameSort nameSort=new ThreadedNameSort();
       ThreadedSalarySort salarySort=new ThreadedSalarySort();

        ExecutorService threadExecutor=Executors.newCachedThreadPool();

        threadExecutor.execute(idSort);
        threadExecutor.execute(nameSort);
        threadExecutor.execute(salarySort);

   }
}

每个线程方法看起来像这样:

public class ThreadedIDSort implements Runnable, EmployeeInterface {
    public synchronized void run(){
        employeeList.sort(new IDComparator());
    }
  }

ID Compartator类如下:

public class IDComparator implements Comparator<Employee> {
    @Override
    public int compare(Employee a, Employee b) {
        return a.getID()-b.getID();
    }

}

employeeList是一个对象列表,具有名称、id、薪水和职位属性:

ArrayList<Employee> employeeList=new ArrayList<>();

虽然我添加了运行前同步方法,但编辑列表仍然会产生ConcurrentModificationException

Exception in thread "pool-2-thread-2" Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList.sort(ArrayList.java:1723)
    at Client.Sort.Threaded.ThreadedNameSort.run(ThreadedNameSort.java:9)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:831)

我试图使用名称,职位和ID一次使用线程排序。

共有2个答案

湛宜春
2023-03-14

Rob Spoor解释了为什么ConcurrentModificationException不一定与线程有关。但是,你也应该知道:

示例中run()方法上的synchronized关键字无效。

当您编写同步方法时,

    public synchronized void bar() {
        ...
    }

这就像你写的一样,

    public void bar() {
        synchronized(this) {
             ...
        }
    }

在您的示例中,提交给executor服务的三个任务中的每一个都是一个不同的Runnable对象。关键字this在三个run()方法中分别引用不同的对象。三个不同的线程在三个不同的对象上同步与完全不同步是一样的。

只有当线程在同一对象上同步时,同步才有意义。规则是,不允许两个线程同时在同一个对象上同步。

荆利
2023-03-14

在单线程应用程序中也可以出现一个并发修改。当对集合进行修改和迭代时,就会出现这种情况。这可以很简单,如下所示:

for (String s : myStringList) {
    if ("X".equals(s)) {
        myStringList.remove(s);
    }
}

请注意,来自java.util.concurrent的所谓并发集合旨在支持此功能,但来自java.util的大多数(全部?)都有相同的问题,即使您应用了同步。

如果没有看到雇员列表到底是什么,以及ID比较器做了什么,就很难说出为什么在这个特定的情况下会引发异常。

 类似资料:
  • 问题内容: 我正在尝试将接口绑定到其实现,如从配置文件中读取的那样,以便可以将其提供给IoC容器。这大致是我想做的事情: 是否有可能获得? 问题答案: 您需要将类显式传递给构造函数(并自行存储)。

  • 问题内容: 在我正在使用的代码下面,可以正常工作并输出名称,但不能使用sort方法。我期望“ Collections.sort(nameFromText);” 按名字的字母顺序对ArrayList进行排序。 我究竟做错了什么? 问题答案: 方法期望要排序的列表元素具有可比性。元素类型应该实现接口,或者您应该使用带有通用实例的重载方法。 在下面的代码中,您不满足上述两个条件。您的类既没有实现,也没有

  • 获得并应用修改 编译qemu还会用到的库文件有 libsdl1.2-dev 等。安装命令如下: sudo apt-get install libsdl1.2-dev # 安装库文件 libsdl1.2-dev 获得 qemu 的安装包以后,对其进行解压缩(如果格式无法识别,请下载相应的解压缩软件)。 例如 qemu.tar.gz/qemu.tar.bz2 文件,在命令行中可以使用: tar

  • 本文向大家介绍JAVA对list集合进行排序Collections.sort(),包括了JAVA对list集合进行排序Collections.sort()的使用技巧和注意事项,需要的朋友参考一下 对一个集合中的对象进行排序,根据对象的某个指标的大小进行升序或降序排序。代码如下: 进行降序排列 进行升序排列 经过测试发现,只需要把两个对象的位置调换一下即可升序或降序。 如果指标相同,根据多个指标进行

  • 我有一个由多个线程操作的ArrayList,由于ArrayList没有同步,所以无法工作。按照教授的指示,我把列表换成了向量。向量是同步的,但我抛出了与同步相关的异常。 为什么会发生这种情况,我如何避免代码中的并发异常?我不想只是玩玩,直到有东西起作用,我想做最好的事情。谢谢! 例外情况: 代码: