我有一个监视服务,它监视ENTRY_DELETEENTRY_CREATEENTRY_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方法中。

10-07 13:11