我们在Jboss 6.4中有一个Web应用程序,它必须检查Folder(new Files),我们的想法是将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 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;
}
}
现在,使用
setThreadFactory()
上的FileAlterationMonitor
设置上述自定义线程工厂。然后,您可以使用自定义
isMonitorThreadAlive()
方法检查它是否仍然存在。另一种粗略但可能更简单的方法是为监视线程命名,并使用
top ThreadGroup
通过给定名称查找线程(并在其上使用isAlive())。以下是一个简单的示例
#Edit:以下内容不能用作FileAlterationMonitor,这是@JOANA_Batista指出的最终类
FileAlterationMonitor monitor = new FileAlterationMonitor(directory) {
@Override
public void run () {
//setting name
Thread.currentThread().setName("monitorThread");
this.run();
}
}
由于无法覆盖
FileAlterationMonitor
,因此必须找到其他方法来更改监视器线程名称。我们可以设置使用FileAlterationListener.onStart()
。由于此方法是在FileAlterationObserver.checkAndNotify()中调用的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
,因为stop方法会破坏观察者。这实际上应该重新启动监视器线程。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();
}
}
最好在调用stop之后再创建所有内容(侦听器,监控器和Obsever),因为没有太多可重用的内容(仅Monitor对象)。
关于java - Commons IO 2.4,如何控制FileAlterationListener的状态并重启,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36673817/