WatchService 和 SwingWorker:如何正确执行?

2024-04-16

WatchService 听起来像是一个令人兴奋的想法......不幸的是,它似乎像教程/api 中警告的那样低级,而且并不真正适合 Swing 事件模型(或者我错过了一些明显的东西,非零概率

获取代码来自教程中的 WatchDir 示例 http://download.oracle.com/javase/tutorial/essential/io/notification.html(简化为仅处理单个目录),我基本上结束了

  • 扩展 SwingWorker
  • 在构造函数中进行注册操作
  • 将等待按键的无限循环放入 doInBackground
  • 通过 key.pollEvents() 检索时发布每个 WatchEvent
  • 通过将删除/创建的文件作为 newValue 触发 propertyChangeEvents 来处理块

    @SuppressWarnings("unchecked")
    public class FileWorker extends SwingWorker<Void, WatchEvent<Path>> {
    
        public static final String DELETED = "deletedFile";
        public static final String CREATED = "createdFile";
    
        private Path directory;
        private WatchService watcher;
    
        public FileWorker(File file) throws IOException {
            directory = file.toPath();
            watcher = FileSystems.getDefault().newWatchService();
            directory.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        }
    
        @Override
        protected Void doInBackground() throws Exception {
            for (;;) {
                // wait for key to be signalled
                WatchKey key;
                try {
                    key = watcher.take();
                } catch (InterruptedException x) {
                    return null;
                }
    
                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();
                    // TBD - provide example of how OVERFLOW event is handled
                    if (kind == OVERFLOW) {
                        continue;
                    }
                    publish((WatchEvent<Path>) event);
                }
    
                // reset key return if directory no longer accessible
                boolean valid = key.reset();
                if (!valid) {
                    break;
                }
            }
            return null;
        }
    
        @Override
        protected void process(List<WatchEvent<Path>> chunks) {
            super.process(chunks);
            for (WatchEvent<Path> event : chunks) {
                WatchEvent.Kind<?> kind = event.kind();
                Path name = event.context();
                Path child = directory.resolve(name);
                File file = child.toFile();
                if (StandardWatchEventKinds.ENTRY_DELETE == kind) {
                    firePropertyChange(DELETED, null, file);
                } else if (StandardWatchEventKinds.ENTRY_CREATE == kind) {
                    firePropertyChange(CREATED, null, file);
                }
            }
        }
    
    }
    

基本思想是让使用代码幸福地不知道粘糊糊的细节:它监听属性更改和 f.i.根据需要更新任意模型:

    String testDir = "D:\\scans\\library";
    File directory = new File(testDir);
    final DefaultListModel<File> model = new DefaultListModel<File>();
    for (File file : directory.listFiles()) {
        model.addElement(file);
    }
    final FileWorker worker = new FileWorker(directory);
    PropertyChangeListener l = new PropertyChangeListener() {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (FileWorker.DELETED == evt.getPropertyName()) {
                model.removeElement(evt.getNewValue());
            } else if (FileWorker.CREATED == evt.getPropertyName()) {
                model.addElement((File) evt.getNewValue());
            }
        }
    };
    worker.addPropertyChangeListener(l);
    JXList list = new JXList(model);

貌似可以用,但是感觉不舒服

  • 我把自己标榜为与线程无关的人:到目前为止,我看到的所有示例片段都通过使用 watcher.take() 来阻塞等待线程。他们为什么这么做?预计至少会有一些人使用 watcher.poll() 并睡一会儿。
  • SwingWorker 发布方法似乎不太适合:现在还好,因为我只观看一个目录(不想在错误的方向上走得太远:)当尝试观看多个目录时(如原始 WatchDir 示例)有多个键,并且 WatchEvent 与其中之一相关。要解析路径,我需要事件和目录[A] 关键是看——但只能传一个。不过,很可能逻辑分布是错误的

[A] Edited(由 @trashgods 的评论触发) - 它实际上不是我必须随事件一起传递的密钥,它是报告更改的目录。相应地改变了问题

仅供参考,这个问题被交叉发布到

Addendum

阅读WatchKey的api文档:

有多个线程从手表检索有信号的键 服务然后应注意确保重置方法是 仅在处理对象的事件后调用。

似乎暗示事件应该

  1. 在检索 WatchKey 的同一线程上进行处理
  2. 钥匙重置后不应触摸

不完全确定,但结合(未来)递归观看目录(多个)的要求,决定遵循 @Eels 的建议,有点 - 很快就会发布我决定的代码

EDIT刚刚接受了我自己的答案 - 如果有人有合理的反对意见,我会谦虚地回复这一点


因为你的后台线程完全用于观看,take() http://download.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html#take%28%29是正确的选择。它有效地隐藏了平台依赖 http://download.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html实现,可以转发或轮询。中的一个poll() http://download.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html#poll%28%29例如,如果您的后台线程还需要检查与该队列串联的其他队列,则方法将是合适的WatchService.

附录:因为WatchKey http://download.oracle.com/javase/7/docs/api/java/nio/file/WatchKey.html有状态,它可能不应该被转发到process(). The context() http://download.oracle.com/javase/7/docs/api/java/nio/file/WatchEvent.html#context%28%29 of a WatchEvent http://download.oracle.com/javase/7/docs/api/java/nio/file/WatchEvent.html is a "relative http://download.oracle.com/javase/7/docs/api/java/nio/file/Path.html#relativize%28java.nio.file.Path%29注册到监视服务的目录与创建、删除或修改的条目之间的路径。”其中之一resolve() http://download.oracle.com/javase/7/docs/api/java/nio/file/Path.html#resolve%28java.nio.file.Path%29如果目录共享公共根,方法应该有效。

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

WatchService 和 SwingWorker:如何正确执行? 的相关文章

  • Amazon Elasticache Redis 集群 - 无法获取端点

    我需要获取 Amazon Elasticache 中 Redis 集群的终端节点 以下代码适用于 Memcached 集群 但不适用于 Redis import com amazonaws auth AWSCredentials impor
  • Hibernate 4 字节码增强不适用于脏检查优化

    我正在使用 Hibernate 4 3 6 并且我使用了最新的Maven 字节码增强 http vladmihalcea com hibernate 4 bytecode enhancement 使所有实体提高自我肮脏意识 我添加了mave
  • Android 中的 java.util.Observable 是线程安全的吗?

    Android 中的 java util Observable 是线程安全的吗 这文档 http developer android com reference java util Observable html说只有deleteObser
  • Java - 红、绿、蓝获取RGB

    通过致电getRGB int x int y with a BufferedImage对象 得到一个负数 如何将三个不同的值 红色 绿色和蓝色 转换为这个单个负数 使用颜色类 new Color r g b getRGB
  • APNS(Apple 推送通知服务器)的反馈服务

    我们正在使用Java作为推送通知提供商APNS I我能够将消息发送到APNS但我不知道如何获得该消息的反馈 请帮忙 反馈服务具有类似于用于发送推送通知的接口的二进制接口 您可以通过以下方式访问生产反馈服务feedback push appl
  • 探索java图像处理的好资源[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是图像处理领域的新手 请推荐一些好的资源 书籍和网络链接 来学习 Java 中的图像处理 最适合隐写术分析 适合初学者和高级水平 我看过
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • Ant 中回显目标描述

  • 想要从java中的char数组创建字符流

    我想从 char 数组构造一个流以使用 java 8 功能 例如过滤器和映射 char list a c e Stream
  • Apache Commons VFS - 无法解析文件

    VFS 方法无法处理此 URI jboss server temp dir local outgoing配置在jboss beans xml这是决心 C Download jboss eap 5 1 1 server default tmp
  • java 中的 Try-with-resources 和 return 语句

    我想知道是否放一个return里面的声明尝试资源block 防止资源自动关闭 try Connection conn return conn createStatement execute 如果我写这样的东西将会联系被关闭 Oracle 文
  • 在 Java 中的 JFrame/JPanel/JComponent 中添加 Web 浏览器

    我正在开发一个 Java 应用程序 需要在应用程序中使用 Web 浏览器 我见过一些应用程序这样做 例如在同一应用程序中单击左侧面板中的提要并打开右侧面板中的链接时的 RSS 阅读器 我想实现类似的功能 在java中可以做到这一点吗 Jav
  • 开发人员实际上是否使用 vim 在 Windows 操作系统上编写代码(Java)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Hazelcast:连接到远程集群

    我们有一组 Hazelcast 节点 全部运行在一个远程系统 具有许多节点的单个物理系统 上 我们希望从外部客户端连接到该集群 一个 Java 应用程序 它使用如下代码连接到 Hazelcast ClientConfig clientCon
  • 单元测试、集成测试还是设计中的问题?

    我编写了我的第一个单元测试 我认为它过于依赖其他模块 我不确定是否是因为 这是一个复杂的测试 我实际上已经编写了集成测试或 我的设计有问题 我首先要说的是 虽然我有大约 4 年的开发经验 但我从未学过 也没有人教过自动化测试 我刚刚使用 H
  • 从特定 JAR 文件读取资源(文件的重复路径)

    假设您有 jar1 和artifactId 动物园 jar2 和artifactId 动物 两个 jar 都有一个具有相同路径的资源文件 例如 animals animal txt 有什么方法可以从特定的 jar 中读取该文件吗 使用 ge
  • Java给定长度的随机数

    我需要在 Java 中生成一个恰好 6 位数字的随机数 我知道我可以在随机发生器上循环 6 次 但是在标准 Java SE 中还有其他方法可以做到这一点吗 要生成 6 位数字 Use Random http download oracle
  • 线程上下文类加载器和普通类加载器的区别

    线程的上下文类加载器和普通类加载器有什么区别 也就是说 如果Thread currentThread getContextClassLoader and getClass getClassLoader 返回不同的类加载器对象 将使用哪一个
  • 如何在apache POI中读取excel文件的准确单元格内容

    当我读取单元格的内容时 例如如果它是日期格式 它会转换为另一个值 例如 12 31 2099 gt 46052 和 50 00 gt 50 和 50 00 gt 0 5 但我想要的是获取每个单元格的确切字符串值 我的代码是这样的 cell
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即

随机推荐

  • 为什么我在此语音识别代码中缺少 an4-1-1.match 文件?

    我在语音识别的解码部分遇到问题 我按照步骤操作here http www speech cs cmu edu sphinx tutorial html 当我输入 perl scripts pl decode slave pl 我收到这些错误
  • AWS从EBS切换到EFS

    我正在考虑从 AWS Elastic Block Storage 切换到 AWS Elastic Filesystem 主要是为了易于扩展 而且可共享存储似乎也不错 目前我有一个 debian EC2 实例和一个 EBS 卷 将数据从 EB
  • Python 中丢弃图像时出现内存泄漏

    我目前正在用 Python 编写一个简单的棋盘游戏 我刚刚意识到当图像重新加载时 垃圾收集不会从内存中清除丢弃的位图数据 仅当游戏启动或加载或分辨率更改时才会发生这种情况 但它会增加消耗的内存 所以我不能让这个问题得到解决 重新加载图像时
  • 什么是IDL?

    IDL 是什么意思 我用谷歌搜索了一下 发现它代表接口定义语言 用于组件的接口定义 但是 在实践中 IDL 的目的是什么 微软使用它吗 接口定义语言 IDL 用于在远程过程调用 RPC 中建立客户端和服务器之间的通信 它有很多变体 例如 S
  • batik-rasterizer.jar - 将 svg 转换为 png

    我尝试使用以下命令在我的 Linux 服务器中设置导出服务器 以将图形下载为图像高图表 http www highcharts com docs export module setting up the server command jav
  • 单击p-dialog关闭(X)按钮时如何调用角度函数?

    单击p dialog关闭 X 按钮时如何调用角度函数 我已经搜索并尝试过这个 onHide cancel 但这不起作用 请分享您的解决方案 我知道我们可以使用close cancel按钮隐藏弹出窗口 但在我的场景中 我想在单击 X 按钮单击
  • 在 Swift 中,如何将现有的二进制文件读入数组?

    作为我的项目的一部分 我有一个二进制数据文件 其中包含大量 32 位整数 我的一个类在初始化时读入该文件 在我的 C 库中 我使用以下初始化程序读入它 Evaluator Evaluator m HandNumbers resize 324
  • 如何在向量列表上应用索引向量?

    我想将一个长索引向量 50 多个非连续整数 应用于一长向量列表 包含 100 多个名称的 50 多个字符向量 以便检索特定值 作为列表 向量或数据帧 一个简化的例子如下 gt my list lt list c a b c c d e f
  • 一步一步 YouTrack“在构建中修复”填充 TeamCity 集成

    我正在使用 TeamCity Professional 8 1 和 YouTrack 5 0 6 我已经成功地用两步工作流程填充了 YouTrack 中的 Fixed in build 字段 我在用 issue id 已修复我的 Mercu
  • R闪亮的csv或excel上传选项

    我需要为用户提供上传 csv txt 或 xlsx 格式文件的选项 我正在使用 xlsx 包 并在我的 UI 上提供了一个单选按钮 例如 ui lt dashboardPage dashboardHeader title SKU Healt
  • 如何在pytorch中查看DataLoader中的数据

    我在 Github 上的示例中看到类似以下内容 如何查看该数据的类型 形状和其他属性 train data MyDataset int 1e3 length 50 train iterator DataLoader train data b
  • 获取脚本路径

    在 CSS 中 任何图像路径都是相对于 CSS 文件位置的 f ex 如果我将 CSS 文件放入 media css mystyles css并使用类似的东西 background url images myimage jpg 浏览器将在以
  • NLTK CoreNLPDependencyParser:无法建立连接

    我正在尝试通过 NLTK 使用斯坦福解析器 按照示例here http www nltk org api nltk parse html nltk parse corenlp CoreNLPDependencyParser 20tutori
  • apache 的子进程返回退出代码 -6,但没有 stdout 或 stderr

    当从 apache 进程运行 git status 甚至 ls 时 我经常得不到标准输出或错误 并且退出状态代码为 6 其他时候 它就有效 有什么想法为什么会发生这种情况或者这意味着什么吗 如果您所在的网络有很多人 则可能会耗尽可用的并发连
  • ASP.Net 动态切换母版页

    以前从未需要这样做 但是是否可以动态设置 更改页面正在使用的母版页 有一个旧的 asp net web 表单项目 我为它创建了一个新的引导模板 但老板希望给人们机会打开新的模板 而不是强迫他们使用 我建议您创建一个 BasePage 类 而
  • Java 中的全局异常处理程序

    我正在考虑使用以下命令为我的 Android 移动应用程序 使用 Java 语法 设置一个全局默认异常处理程序Thread setDefaultUncaughtExceptionHandler 称呼 我正在考虑只向用户显示一个带有适当消息的
  • 更改值 recyclerview.adapter 并将其保存到 mainactivity 中的 textview 中?

    当我更改 recyclerview adapter 的值时 我想将其值设置为 mainactivity 中的 textview 该怎么做 it will be like this 从我的 json 中检索回收数据 因此它将是随机的且数据很多
  • Flutter:如何导入现有的 Flutter 项目作为 gradle 项目

    如何导入现有的 Flutter 项目作为 gradle 项目 导入项目 向导要求 Gradle 主路径 我的系统中安装了 gradle 但这里需要设置什么 哪个路径 这是我正在尝试的 Error 我也遇到过这个问题 我必须在 Android
  • 使用 scikit-learn OneClassSVM 时获取每个新观察结果为异常值的概率

    我是 scikit learn 和 SVM 方法的新手 我的数据集与 scikit learn OneClassSVM 配合良好 可以检测异常值 我使用观察来训练 OneClassSVM 所有这些都是 内点 然后使用 Predict 对我的
  • WatchService 和 SwingWorker:如何正确执行?

    WatchService 听起来像是一个令人兴奋的想法 不幸的是 它似乎像教程 api 中警告的那样低级 而且并不真正适合 Swing 事件模型 或者我错过了一些明显的东西 非零概率 获取代码来自教程中的 WatchDir 示例 http