Java: Как ждать выполнения fileChanged? - PullRequest
2 голосов
/ 08 ноября 2010

Я бы хотел, чтобы мой поток (основной / EDT) дождался изменения файла, а затем дождался DefaultFileMonitor расширяет Runnable и, следовательно, работает в собственном потоке. Вот SSCE:

import java.io.File;
import org.apache.commons.vfs.*;
import org.apache.commons.vfs.impl.DefaultFileMonitor;

public class FileChangeListener implements FileListener {
    DefaultFileMonitor fm;
    public final static File logFile = new File("t.txt");

 public void startListening() throws FileSystemException {
    final FileSystemManager fsManager = VFS.getManager();
    final FileObject listendir = fsManager.toFileObject(logFile);

    fm = new DefaultFileMonitor(this);
    fm.addFile(listendir);
    fm.start();
}

     @Override
public void fileCreated(FileChangeEvent fce) throws Exception {
    fileChanged(fce);
}

@Override
public void fileDeleted(FileChangeEvent fce) throws Exception {
    //hmm..why deleted?
}

@Override
public void fileChanged(FileChangeEvent fce) throws Exception {
    System.out.println("fileChanged executed");
}
}

Основное:

import java.io.PrintWriter;

public class App {

public static void main(String[] args) {
    FileChangeListener fcl = new FileChangeListener();
    try {
        fcl.startListening();
        final PrintWriter printWriter = new PrintWriter(FileChangeListener.logFile);
        printWriter.println("Hello Threads!");
        printWriter.close();

        //EXECUTE THE FOLLOWING ONLY AFTER fileChanged
        System.out.println("Mission complete.");
    } catch (Exception ex) {
    }
}
}

Ответы [ 3 ]

1 голос
/ 08 ноября 2010

Добавьте следующее к значению App.main (..) после printWriter.close ():

            synchronized (fcl) {
                fcl.wait();
            }
            //EXECUTE THE FOLLOWING ONLY AFTER fileChanged
            System.out.println("Mission complete.");

и добавьте следующее к FileChangeListener.fileChanged (..) после System.out.println ("fileChanged execute"):

synchronized (this) {
        this.notifyAll();
    }
1 голос
/ 08 ноября 2010

Вы можете общаться между двумя, используя «Условия»: http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html

По сути, создайте новый "общий доступ" Condition (скажем, fileChanged). Теперь при каждом изменении файла (в fileChanged() запускается это условие (fileChanged.signal()). В основном коде дождитесь возникновения этого условия (fileChanged.await()).

Надеюсь, вы поняли идею.


Чтобы сделать условие доступным для нескольких единиц кода, я могу подумать вот о чем (уменьшая порядок предпочтений):

  1. Предполагая, что вам потребуется столько условий, сколько файлов вы слушаете, создайте фабричный метод getCondition(String file path/name/attribute), который будет возвращать объект Condition на основе файла (его путь или имя или другие атрибуты). Используйте этот фабричный метод, чтобы получить условие во всех случаях. Фабрика должна внутренне создавать new Condition() экземпляров для каждого нового файла, который нужно прослушивать, И должна отбрасывать более старые экземпляры, когда обработка файлов завершена (поэтому, вероятно, вам следует также добавить метод destroy/deleteCondition(String file).)
  2. Сохраните условие как public поле в классе слушателя (что-то вроде хака, если у вас есть экземпляр слушателя).
  3. Сохранить условие в виде поля public static в классе слушателя (хак, если у вас всего один экземпляр слушателя).
0 голосов
/ 08 ноября 2010

Почему? FileChangeListener является обратным вызовом: он выполняется , когда происходит событие. В этом конкретном случае вы только что закрыли файл, так что вы уже знаете, что миссия завершена для этого файла, поэтому просто перейдите к следующему шагу. Я не понимаю, зачем вам вообще нужен FileChangeListener.

...