我试图编写一个文件监视器,它将检查文件是否添加了新行,该监视器实际上是一个线程,它将始终由randomaccessfile读取该行。
这是监视器的核心代码:
public class Monitor { public static Logger log = Logger.getLogger(Monitor.class); public static final Monitor instance = new Monitor(); private static final ArrayList<Listener> registers = new ArrayList<Listener>(); private Runnable task = new MonitorTask(); private Thread monitorThread = new Thread(task); private boolean beStart = true; private static RandomAccessFile raf = null; private File monitoredFile = null; private long lastPos; public void register(File f, Listener listener) { this.monitoredFile = f; registers.add(listener); monitorThread.start(); } public void replaceFile(File newFileToBeMonitored) { this.monitoredFile = newFileToBeMonitored; // here,how to restart the monitorThread? } private void setRandomFile() { if (!monitoredFile.exists()) { log.warn("File [" + monitoredFile.getAbsolutePath() + "] not exist,will try again after 30 seconds"); try { Thread.sleep(30 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } setRandomFile(); return; } try { if (raf != null) { raf.close(); lastPos = 0; } raf = new RandomAccessFile(monitoredFile, "r"); log.info("monitor file " + monitoredFile.getAbsolutePath()); } catch (FileNotFoundException e) { // The file must exist now } catch (IOException e) {} } private void startRead() { beStart = true; String line; while (beStart) { try { raf.seek(lastPos); while ((line = raf.readLine()) != null) { fireEvent(new FileEvent(monitoredFile.getAbsolutePath(), line)); } lastPos = raf.getFilePointer(); } catch (IOException e1) {} } } private void stopRead() { this.beStart = false; } private void fireEvent(FileEvent event) { for (Listener lis : registers) { lis.lineAppended(event); } } private class MonitorTask implements Runnable { @Override public void run() { stopRead(); //why putting the resetReandomAccessFile in this thread method is that it will sleep if the file not exist. setRandomFile(); startRead(); } } }
这是一些帮助类:
public interface Listener { void lineAppended(FileEvent event); } public class FileEvent { private String line; private String source; public FileEvent(String filepath, String addedLine) { this.line = addedLine; this.source = filepath; } //getter and setter }
这是调用监视器的示例:
public class Client implements Listener { private static File f = new File("D:/ab.txt"); public static void main(String[] args) { Monitor.instance.register(f, new Client()); System.out.println(" I am done in the main method"); try { Thread.sleep(5000); Monitor.instance.replaceFile(new File("D:/new.txt")); } catch (InterruptedException e) { System.out.println(e.getMessage()); } } @Override public void lineAppended(FileEvent event) { String line = event.getLine(); if (line.length() <= 0) return; System.err.println("found in listener:" + line + ":" + line.length()); } }
现在,我的问题是,如果我仅调用以下代码,代码就可以很好地工作:
Monitor.instance.register(file,listener);
这将监视文件的行追加,并通知侦听器。
但是,当我致电:
Monitor.instance.replaceFile(anotherfile);
这意味着我想监视另一个文件而不是之前。
因此,在Monitor中,我必须重新启动线程,该怎么做?
我已经尝试过:
monitorThread.interruppt();
它不会扭曲。
任何人都可以为我修复它或告诉我该怎么做?
谢谢。
在我询问之前,我已经搜索了“重新启动Java线程”,因此我知道一个无法重新启动死线程,但是我的线程不返回,因此我认为可以重新启动它。
我没有解释,只是编写了一个框架示例。我没有对它进行很好的测试,但这可能有一定用处。
为了监视(另一个)文件,只需创建一个新的Monitor,并向其传递ScheduledExecutorService。启动和停止监视非常简单。您可以(应该)将同一个执行程序重用于多个监视器。
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public interface Event { } public interface Listener { void handle(Event event); } public class Monitor { private static final int CHECK_EVERY_SECONDS = 10; private static final int RECHECK_AFTER_IF_NOT_EXISTS_SECONDS = 30; private File file; private ScheduledExecutorService executor; private boolean active; private List<Listener> listeners; public Monitor(File file, ScheduledExecutorService executor) { super(); this.file = file; this.executor = executor; listeners = new ArrayList<Listener>(); } public synchronized void start() { if (active) { return; } active = true; executor.execute(new Runnable() { public void run() { synchronized (Monitor.this) { if (!active) { System.out.println("not active"); return; } } if (!file.exists()) { System.out.println("does not exist, rescheduled"); executor.schedule(this, RECHECK_AFTER_IF_NOT_EXISTS_SECONDS, TimeUnit.SECONDS); return; } Event event = doStuff(file); System.out.println("generated " + event); updateListeners(event); System.out.println("updated listeners and rescheduled"); executor.schedule(this, CHECK_EVERY_SECONDS, TimeUnit.SECONDS); } }); } private Event doStuff(final File file) { return new Event() { public String toString() { return "event for " + file; } }; } public synchronized void stop() { active = false; } public void addListener(Listener listener) { synchronized (listeners) { listeners.add(listener); } } public void removeListener(Listener listener) { synchronized (listeners) { listeners.remove(listener); } } private void updateListeners(Event event) { synchronized (listeners) { for (Listener listener : listeners) { listener.handle(event); } } } public static void main(String[] args) throws IOException { ScheduledExecutorService executor = Executors.newScheduledThreadPool(4); File file = new File("test.png"); Monitor monitor = new Monitor(file, executor); monitor.addListener(new Listener() { public void handle(Event event) { System.out.println("handling " + event); } }); monitor.start(); System.out.println("started..."); System.in.read(); monitor.stop(); System.out.println("done"); executor.shutdown(); } }