开发者

Java: How to wait for fileChanged to execute?

I'd like to have my thread (the main/EDT) wait until changes to a file occur and then wait. DefaultFileMonitor extends Runnable and hence runs in a thread of its own. Here is a 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 开发者_Go百科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");
}
}

The main:

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) {
    }
}
}


Append the following to App.main(..) after printWriter.close():

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

and append the following to FileChangeListener.fileChanged(..) after System.out.println("fileChanged executed"):

synchronized (this) {
        this.notifyAll();
    }


You could communicate between teh two using "Conditions" : http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html

Basically, create a new "shared" Condition (say fileChanged). Now, whenever the file changes (in fileChanged() trigger this condition (fileChanged.signal()). In your main code, wait for this condition to occur (fileChanged.await()).

Hope you get the idea.


For making the condition accessible to multiple code unit, here is what I can think (decreasing order of preference) :

  1. Assuming you are going to need as many conditions as many files you listen to, create a factory method getCondition(String file path/name/attribute) which will return the Condition object based on the file (its path or name or other attributes). Use this factory method to get the condition in all cases. The factory should internally create new Condition() instances for each new file to be listened to AND must throw away older instances as the processing of the files is complete (so probably you should add a destroy/deleteCondition(String file) method as well.)
  2. Store the condition as a public field in the listener class (kind of hack if you have the listener instance available).
  3. Store the condition as a public static field in the listener class (kind of hack if you have only one listener instance throughout).


Why? FileChangeListener is a callback: it is executed when the event occurs. In this specific case you've just closed the file so you alreayd know that the mission is complete on that file, so just proceed to the next step. I don't see why you need a FileChangeListener at all here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜