gpt4 book ai didi

java - WatchService 和 SwingWorker : how to do it correctly?

转载 作者:搜寻专家 更新时间:2023-10-30 21:28:40 25 4
gpt4 key购买 nike

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

获取代码from WatchDir example in the tutorial (简单地只处理单个目录),我基本上结束了

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

    @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。要解析路径,我需要事件和 key 正在监视的 目录 [A] - 但只能传递一个。不过,很可能逻辑分布有误

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

仅供引用,此问题已交叉发布到 OTN swing forum

附录

阅读 WatchKey 的 api 文档:

Where there are several threads retrieving signalled keys from a watch service then care should be taken to ensure that the reset method is only invoked after the events for the object have been processed.

似乎暗示事件应该

  1. 在检索 WatchKey 的同一线程上进行处理
  2. 按键复位后不可触摸

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

编辑刚刚接受了我自己的回答 - 如果有人有合理的反对意见,我会谦虚地回复

最佳答案

因为您的后台线程完全用于观看,take()是正确的选择。它有效地隐藏了 platform dependent实现,它可以转发或轮询。 poll()之一例如,如果您的后台线程还需要检查与 WatchService 串联的其他队列,方法将是合适的。

附录:因为 WatchKey有状态,它可能不应该被转发到 process()context()WatchEvent是“relative 注册到监视服务的目录与创建、删除或修改的条目之间的路径。” resolve()之一如果目录共享一个公共(public)根,方法应该有效。

关于java - WatchService 和 SwingWorker : how to do it correctly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7784909/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com