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

如何避免来自JFileChooser的ConcurrentModificationException。setFileFilter()调用?

常雪风
2023-03-14

我有下面的代码,只是得到了并发修改异常。

fchProtocol = new FileChooser(lastFileLoc);
FileNameExtensionFilter xmlfilter = new FileNameExtensionFilter("xml files (*.xml)", "xml");
fchProtocol.setFileFilter(xmlfilter);  <<<< ***** exception from here

异常跟踪信息:

java.util.ConcurrentModificationException
    java.util.Vector$Itr.checkForComodification(Vector.java:1184)
    java.util.Vector$Itr.next(Vector.java:1137)
    javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:340)
    javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:346)
    javax.swing.plaf.basic.BasicDirectoryModel.validateFileCache(BasicDirectoryModel.java:135)
    javax.swing.plaf.basic.BasicDirectoryModel.propertyChange(BasicDirectoryModel.java:69)
    java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
    java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
    java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
    java.awt.Component.firePropertyChange(Component.java:8422)
    javax.swing.JFileChooser.setFileFilter(JFileChooser.java:1473)

这是JavaAPI方法代码,是抛出异常的最后一行。

public void setFileFilter(FileFilter filter) {
        FileFilter oldValue = fileFilter;
        fileFilter = filter;
        if (filter != null) {
            if (isMultiSelecthtml" target="_blank">ionEnabled() && selectedFiles != null && selectedFiles.length > 0) {
                Vector<File> fList = new Vector<File>();
                boolean failed = false;
                for (File file : selectedFiles) {
                    if (filter.accept(file)) {
                        fList.add(file);
                    } else {
                        failed = true;
                    }
                }
                if (failed) {
                    setSelectedFiles((fList.size() == 0) ? null : fList.toArray(new File[fList.size()]));
                }
            } else if (selectedFile != null && !filter.accept(selectedFile)) {
                setSelectedFile(null);
            }
        }
        firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
    }

这发生在GUI初始化阶段。xmlfileter是一个局部变量。

我在Linux中使用的是javaVersion=1.8.0_20。这是不可复制的,今年在我的开发过程中只发生了三次。

我不知道如何避免这种情况,或者如何正确使用文件选择器及其文件过滤器。有人能帮我吗?

编辑:

它发生在应用程序初始化阶段:

  1. 主线程以main()开头。
  2. 在主线程中初始化了几个非GUI类
  3. 打电话

.

SwingUtilities.invokeAndWait(new Runnable()

    public void run()
    {    
         initalize GUI classes from here    
    }    
);

进行GUI初始化,但在最初的几个步骤中,GUI初始化线程失败。GUI初始化线程中没有其他线程。而且主线程没有访问GUI初始化线程的操作。

Basic此时有两个线程:主线程和通过invorkAndWait()调用启动的GUI初始化线程。

共有2个答案

程成天
2023-03-14

这并不是一个真正的答案,但可能对其他提出这个问题的人有用。

这绝对是2014年https://bugs.openjdk.java.net/browse/JDK-8068244的表现。刚刚在Java9.0.1/视窗10中发生,在一个JFrame构造函数中抛出在EDT上,非常类似于OP描述的。

java.util.ConcurrentModificationException
    at java.base/java.util.Vector$Itr.checkForComodification(Unknown Source)
    at java.base/java.util.Vector$Itr.next(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel$FilesLoader.cancelRunnables(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel$FilesLoader.cancelRunnables(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel.validateFileCache(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel.propertyChange(Unknown Source)
    at java.desktop/java.beans.PropertyChangeSupport.fire(Unknown Source)
    at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
    at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
    at java.desktop/java.awt.Component.firePropertyChange(Unknown Source)
    at java.desktop/javax.swing.JFileChooser.setFileFilter(Unknown Source)
    at com.example.ExampleJFrame.initFileChoosers(Unknown Source)
    at com.example.ExampleJFrame.<init>(Unknown Source)
    at com.example.ExampleJFrame$15.run(Unknown Source)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.EventQueue.access$500(Unknown Source)
    at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

导致它的代码通过SwingUtilities在EDT上正确执行。invokeLater()如stacktrace所示。initFileChoosers()方法仅实例化几个文件选择器,为它们调用setFileFilter(),有时会按顺序多次调用。

当然不能复制。

邓夕
2023-03-14

如果你在事件调度线程之外的其他线程上做图形用户界面的事情,这种事情在Swing中总是会发生。尤其是“不可复制”是一个线索。这是一个并发线程处理图形用户界面的时间问题,而只有EDT应该这样做。查看此处了解更多信息。所以在你的情况下,将图形用户界面相关的东西包装在SwingUtilities.invoke稍后中:

final FileFilter oldValue = fileFilter;
...
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
    }
});
 类似资料:
  • 问题内容: 我收到mongodb关于THP的以下警告 但是我确实设法手动关闭了THP 我加入的伎俩,以中和添加 至 我到底该如何避免该警告? 问题答案: MongoDB官方文档为该问题提供了几种解决方案。您也可以尝试此解决方案,该解决方案对我有用: 注意: 如果MongoDB版本大于3.0, 请尝试使用官方文档指令 __ 打开文件。 (如果没有此类文件,您可以检查,文件-信用:以下评论) 在紧接着

  • 问题内容: 我正在使用以下代码通过AJAX提交表单: 背景 我的PHP处理程序执行各种任务,然后发回响应。然后,我可以在成功或错误函数中执行某些操作。 我的问题 当用户双击表单的“提交”按钮时,将发生两次AJAX调用,这将导致我的PHP处理程序中的代码执行两次。 我的问题 如果用户双击提交,如何避免我的代码执行两次? 问题答案: 当AJAX调用再次出现时,请先禁用首次单击的“提交”按钮,然后重新启

  • 问题内容: 我有一个包含一些键(字符串)和值(POJO)的地图 我想遍历此映射并更改POJO中的某些数据。 我继承的当前代码将删除给定的条目,并在对POJO进行一些更改后将其重新添加。 这不能很好地进行,因为在遍历地图时您不应该修改地图(方法已同步,但ConcurrentModificationException仍然出现) 我的问题是 ,如果我需要遍历地图并更改值,我可以使用的最佳实践/方法是什么

  • 本文向大家介绍如何避免回调地狱?相关面试题,主要包含被问及如何避免回调地狱?时的应答技巧和注意事项,需要的朋友参考一下 你可以有以下方式避免回调地狱 模块化:将回调函数转换为独立的函数 使用流程控制库,例如[aync] 使用Promise 使用aync/await 使用来计算生成器或Promise 解析:这个问题有很多种答案,取决你使用的场景,例如ES6, ES7,或者一些控制流库。  

  • 问题内容: 我遇到了ConcurrentModificationException,通过查看它,我看不到它发生的原因。引发异常的区域和所有修改集合的地方都被包围 我试图抓住讨厌的线程,但我能钉钉子(通过在异常中设置断点)是投掷线程拥有监视器,而另一个线程(程序中有两个线程)处于睡眠状态。 我应该如何进行?遇到类似的线程问题时,通常会做什么? 问题答案: 它可能与同步块无关。当您在迭代集合的元素时修

  • 问题内容: 我们都知道您由于以下原因而无法执行以下操作: 但这显然有时有效,但并非总是如此。这是一些特定的代码: 当然,这导致: 即使没有多个线程。无论如何。 解决此问题的最佳方法是什么?如何在不引发此异常的情况下循环地从集合中删除项目? 我还在这里使用任意值,不一定是an t,因此您不能依赖。 问题答案: 是安全的,您可以这样使用它: 注意,这是在迭代过程中修改集合的唯一安全方法。如果在进行迭代