Commons IO 2.4,如何控制FileAlterationListener的状态并重启

Commons IO 2.4, how control the state of FileAlterationListener and restart

我们在 Jboss 6.4 中有一个必须检查文件夹(新文件)的网络应用程序,我们的想法是将 Commons IO 2.4 与 FileAlterationMonitor 一起使用,就像我们想要控制监视器的备份一样。如果是否正常工作,

为此..我们创建了一个 TimerTask 来控制线程是否 运行 如果不是,则创建另一个观察者以继续工作。

我们的问题:

现在在我们的测试中,我们引发了一个异常来杀死观察者并检测他是否不工作并再次重新启动,但我们不知道我们必须如何在 FileAlterationMonitor、FileAlterationObserver 或 FileAlterationListener 中执行此操作,以及如何?

public class App {

  private static final String FOLDER ="/Folder";
  private static final FileAlterationMonitor monitor = new FileAlterationMonitor(1000);

  public static void main(String[] args) throws Exception {

    final File directory = new File(FOLDER);
    FileAlterationObserver fao = new FileAlterationObserver(directory);
    fao.addListener(new FileAlterationListenerImpl());
    monitor.addObserver(fao);

    monitor.start();


      TimerTask task = new TimerTask() {
          @Override
          public void run() {
            System.out.println("Monitor Controler");

            ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
            int noThreads = currentGroup.activeCount();
            Thread[] lstThreads = new Thread[noThreads];
            currentGroup.enumerate(lstThreads);

            for (int i = 0; i < noThreads; i++) {
                System.out.println("Thread No:" + i + " = "+ lstThreads[i].getName());
                System.out.println(lstThreads[i].getState().toString());
                System.out.println(lstThreads[i].isInterrupted());
                System.out.println(lstThreads[i].isAlive());
            }

                for (FileAlterationObserver o :monitor.getObservers()) {
                    String obName = o.toString();
                    String obDir = o.getDirectory().toString();

                    for(FileAlterationListener l :o.getListeners()){
                      String listener = l.toString();

                    }

          }
        };

        Timer timer = new Timer();
        long delay = 0;
        long intevalPeriod = 1 * 1000; 

        // schedules the task to be run in an interval 
        timer.scheduleAtFixedRate(task, delay, intevalPeriod);

  }

}

我的解决方案:

   public class App {

  private static final String FOLDER = "/Folder/";
  private static final FileAlterationMonitor monitor = new FileAlterationMonitor(1000);


  public static void main(String[] args) throws Exception {

    final File directory = new File(FOLDER);
    FileAlterationObserver fao = new FileAlterationObserver(directory);
    fao.addListener(new FileAlterationListenerImpl());

    monitor.addObserver(fao);
    monitor.start();

      TimerTask task = new TimerTask() {
          @Override
          public void run() {

            ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
            int noThreads = currentGroup.activeCount();
            Thread[] lstThreads = new Thread[noThreads];
            currentGroup.enumerate(lstThreads);

            boolean isDead = true;
            for (int i = 0; i < noThreads; i++) {

//              System.out.println("Thread No:" + i + " = "+ lstThreads[i].getName());
//              System.out.println("getState: "+lstThreads[i].getState().toString());
//              System.out.println("isInterrupted: "+ lstThreads[i].isInterrupted());
//              System.out.println("isAlive: "+lstThreads[i].isAlive());

                if(lstThreads[i].getName().equals("monitorThread"))
                {                   
                    isDead= false;          
                }
            }

            if(isDead){
                try {
                    monitor.stop();
                    monitor.start();
                    isDead = false;
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

          }
        };

        Timer timer = new Timer();
        long delay = 0;
        long intevalPeriod = 1 * 1000; 

        timer.scheduleAtFixedRate(task, delay, intevalPeriod);

  }

}

在我的 FileAlterationListenerImpl 中:

@Override
    public void onStart(final FileAlterationObserver observer) {

        Thread.currentThread().setName("monitorThread");

是我唯一可以设置线程名称的地方..

您可以在 FileAlterationMonitor 上使用 setThreadFactory() 方法来设置自定义线程工厂。要了解监视器所在线程的状态 运行 我们需要访问它的实例。

所以创建一个自定义 ThreadFactory class 如下。

class SimpleThreadFactory implements ThreadFactory {
    private Thread monitorThread;
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        if( r instanceof FileAlterationMonitor) {
            monitorThread = thread;
        }

        return thread;
    }

    public boolean isMonitorThreadAlive() {
        boolean isAlive = false;
        if(monitorThread != null) {
            isAlive = monitorThread.isAlive();
        }
        return isAlive;
    }
}

现在使用 FileAlterationMonitor 上的 setThreadFactory() 来设置上面的自定义线程工厂。

然后你可以使用自定义 isMonitorThreadAlive() 方法来检查它是否还活着。

另一种粗略但可能更简单的方法是给监视线程一个名称并使用 top ThreadGroup 通过给定名称查找线程(并在其上使用 isAlive())。

以下是一个简单示例

#Edit:以下不能使用,因为 FileAlterationMonitor 是最终的 class 正如@JOANA_Batista

所指出的
FileAlterationMonitor monitor = new FileAlterationMonitor(directory) {
    @Override
    public void run () {
        //setting name
        Thread.currentThread().setName("monitorThread");
        this.run();
    }
}

因为我们不能覆盖 FileAlterationMonitor 我们必须找到一些其他方法来更改监视器线程名称。我们可以设置使用 FileAlterationListener.onStart().

因为在 FileAlterationObserver.checkAndNotify() which is called in the FileAlterationMonitor.run()

上调用了此方法

FileAlterationMonitor.run()

public void run() {
    while (running) {
        for (FileAlterationObserver observer : observers) {
            observer.checkAndNotify();
        ...

FileAlterationObserver.checkAndNotify()

public void checkAndNotify() {

    /* fire onStart() */
    for (FileAlterationListener listener : listeners) {
        listener.onStart(this);
    }
    ...

这一切都发生在同一个监视器线程上,这就是为什么下面的代码应该在 FileAlterationListener.onStart()

中设置监视器线程名称
@Override
void onStart(final FileAlterationObserver observer) {
    Thread.currentThread().setName("monitorThread");
    ...
}

注意: 您可以在 FileAlterationMonitor 上调用 stop() 方法来停止()线程,但是要再次启动它,您必须添加新的 FileAlterationObserver 再次停止方法破坏了观察者。这实际上应该重新启动监视器线程。

public synchronized void stop(long stopInterval) throws Exception {
    if (running == false) {
        throw new IllegalStateException("Monitor is not running");
    }
    running = false;
    try {
        thread.join(stopInterval);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    /***** Observers are destroyed here ****/
    for (FileAlterationObserver observer : observers) {
        observer.destroy();
    }
}

可能最好在调用停止后再次创建所有内容(Listener、Monitor 和 Obsever),因为没有太多(只有 Monitor 对象)可以重用。