我有一个监视服务,它监视ENTRY_DELETE
、ENTRY_CREATE
和ENTRY_MODIFY
事件的目录,并根据事件执行逻辑。
我需要服务来观察所有更改的目录,而不是退出循环。但我也需要进入我的另一个逻辑。
如何将这些方法重构成Runnable
来完成此任务?
下面的代码。
public static void main(String[] args) {
System.out.println("Started watching");
FileServices fileServices = new FileServicesImpl();
fileServices.setSrcDir(fileServices.getValue("srcdir","properties/abc.properties"));
fileServices.setDestDir(fileServices.getValue("destdir","properties/abc.properties"));
System.out.println(fileServices.getSrcDir());
System.out.println(fileServices.getDestDir());
Map<String,WatchEvent> files = new HashMap<>();
MappingConsole mappingConsole = new MappingConsole();
for(;;){
files = fileServices.getEventMap();
for(String f : files.keySet()){
System.out.println("Size of files: "+files.size());
if (files.get(f).kind() == ENTRY_CREATE || files.get(f).kind() == ENTRY_MODIFY) {
System.out.println("Processing: " +f);
mappingConsole.map940(fileServices.getSrcDir(),f,fileServices.getDestDir());
System.out.println("Processed: " +f);
}
}
}
}
从文件服务实现:
@Override
public void monitorSrcDir(String srcDir){
for(;;){
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Path myDir = Paths.get(srcDir);
WatchService watcher = myDir.getFileSystem().newWatchService();
myDir.register(watcher, ENTRY_CREATE,ENTRY_DELETE, ENTRY_MODIFY);
WatchKey watchKey = watcher.take();
List<WatchEvent<?>> events = watchKey.pollEvents();
for (WatchEvent event : events) {
if (event.kind() == ENTRY_CREATE) {
System.out.println("Create: " + event.context().toString());
getEventMap().put(event.context().toString(), event);
}
if (event.kind() == ENTRY_DELETE) {
System.out.println("Delete: " + event.context().toString());
getEventMap().put(event.context().toString(), event);
}
if (event.kind() == ENTRY_MODIFY) {
System.out.println("Modify: " + event.context().toString());
getEventMap().put(event.context().toString(), event);
}
}
watchKey.reset();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
最佳答案
我这样做:
public class WatchServiceMonitor implements Monitor, Runnable, Closeable {
private static Logger log = LoggerFactory.getLogger( WatchServiceMonitor.class.getName() );
private Destination destination;
private Path hotFolder;
private Thread thread;
public WatchServiceMonitor( Path hotFolder, Destination destination ) {
this.hotFolder = hotFolder;
this.destination = destination;
}
@Override
public void close() throws IOException {
try {
stop();
}
catch ( InterruptedException e ) {
log.warn( "request to stop failed, guess its time to stop being polite!" );
}
}
@Override
public void join() throws InterruptedException {
thread.join();
}
@Override
public void run() {
try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
if ( log.isTraceEnabled() ) log.trace( "registering create watcher on " + hotFolder.toAbsolutePath().toString() );
hotFolder.register( watcher, StandardWatchEventKinds.ENTRY_CREATE );
if ( log.isDebugEnabled() ) log.debug( "watcher registration complete for " + hotFolder.toAbsolutePath().toString() );
synchronized ( this ) {
this.notifyAll();
}
for ( ;; ) {
if ( thread.isInterrupted() ) break;
WatchKey key = null;
try {
log.trace( "waiting for create event" );
key = watcher.take();
log.trace( "got an event, process it" );
}
catch ( InterruptedException ie ) {
log.trace( "interruped, must be time to shut down..." );
break;
}
for ( WatchEvent<?> eventUnknown : key.pollEvents() ) {
WatchEvent.Kind<?> kind = eventUnknown.kind();
if ( kind == StandardWatchEventKinds.OVERFLOW ) return;
@SuppressWarnings( "unchecked" )
WatchEvent<Path> eventPath = (WatchEvent<Path>) eventUnknown;
Path path = hotFolder.resolve( eventPath.context() );
log.trace( "calling destination.transfer({})", path );
destination.transfer( path );
log.info( "transferred {} to destination" );
if (! key.reset()) {
break;
}
}
}
}
catch ( IOException ioe ) {
log.error( ioe.getMessage(), ioe );
}
log.debug( "existing run loop" );
}
@Override
public void start() throws InterruptedException {
log.trace( "starting monitor" );
thread = new Thread( this );
thread.start();
synchronized ( this ) {
this.wait();
}
log.trace( "monitor started" );
}
@Override
public void stop() throws InterruptedException {
log.trace( "stopping monitor" );
thread.interrupt();
thread.join();
thread = null;
log.trace( "monitor stopped" );
}
}
Destination
类是我自己的类之一,它知道如何从WatchService
事件指示的路径进行传输。所以,本质上,我只是将整个
WatchService
循环包装在run
实例的Runnable
方法中。