java 1.7watchservice特性学习 文件变更监控

一、首先概述1.7版本上面的这个java.nio.file.WatchService类

1.1 WatchService 可以干什么?

WatchService可以帮助我们监控一些文件是否做了更改,如果文件做了更改,可以帮助我们去做一些响应,比如,配置文件修改了,那么系统应该重新加载一下配置文件,这样可以将最新的配置加载进来。

 

1.2 完成文件监控一些很重要的类

The watch service exits when either the thread exits or when it is closed (by invoking its closed method。当前启动的线程退出或者调用closed方法关闭的时候,watch service也会推出。

1.2.1 java.nio.file.WatchKey类 

此类代表着一个Object(文件或者文件夹) 注册到WatchService后,返回一个WatchKey类。反应当前所注册的Object状态的类。此类封装了不同事件的状态值,比如,当文件(文件夹)被修改或者被删除或者创建的时候,此类首先产生一个信号量,等待消费者来取并且该WatchKey将会进入到WatchService的队列中。如果WatchKey已经进入到队列当中,但是又有了变化,将不会再次进入到队列当中。

WatchService.take()方法可以取到队列的WatchKey.

1.2.2 java.nio.file.Path类

此类代表文件系统上面的一个文件

1.2.2 java.nio.file.WatchEvent类

此类代表文件的一个具体事件。

WatchEvent

1.3 原理探讨(参考

To implement this functionality, called file change notification, a program must be able to detect what is happening to the relevant directory on the file system. One way to do so is to poll the file system looking for changes, but this approach is inefficient. It does not scale to applications that have hundreds of open files or directories to monitor.

要做到文件变更提醒功能,有一种办法就是轮询文件系统上面的文件确认是否有变更,但是显然这种做法效率不高。

The java.nio.file package provides a file change notification API, called the Watch Service API. This API enables you to register a directory (or directories) with the watch service. When registering, you tell the service which types of events you are interested in: file creation, file deletion, or file modification. When the service detects an event of interest, it is forwarded to the registered process. The registered process has a thread (or a pool of threads) dedicated to watching for any events it has registered for. When an event comes in, it is handled as needed.

Java WatchService 服务提供API,可以注册你感兴趣的事件,当service 发现注册的事件后,就交给处理线程做处理。

1.4 使用注意事项

1.4.1 收到变更事件时候,是否变更已经完成

当收到一个文件变更事件的时候,并不表示该文件已经变更完毕,有可能还在变更当中。

1.4.2 什么时候使用Watch Service比较好.

The Watch Service API is designed for applications that need to be notified about file change events. It is well suited for any application, like an editor or IDE, that potentially has many open files and needs to ensure that the files are synchronized with the file system. It is also well suited for an application server that watches a directory, perhaps waiting for .jsp or .jar files to drop, in order to deploy them.

This API is not designed for indexing a hard drive. Most file system implementations have native support for file change notification. The Watch Service API takes advantage of this support where available. However, when a file system does not support this mechanism, the Watch Service will poll the file system, waiting for events.

1.5 亲自测试

Oracle 官方给出的例子代码:

package com.hpe.common.audit;


/*
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.nio.file.*;
import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;

/**
 * Example to watch a directory (or tree) for changes to files.
 */

public class WatchDir {

    private final WatchService watcher;
    private final Map<WatchKey,Path> keys;
    private final boolean recursive;
    private boolean trace = false;

    @SuppressWarnings("unchecked")
    static <T> WatchEvent<T> cast(WatchEvent<?> event) {
        return (WatchEvent<T>)event;
    }

    /**
     * Register the given directory with the WatchService
     */
    private void register(Path dir) throws IOException {
    	
        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        
        if (trace) {
        	
            Path prev = keys.get(key);
            
            if (prev == null) {
            	
                System.out.format("register: %s\n", dir);
                
            } else {
            	
                if (!dir.equals(prev)) {
                	
                    System.out.format("update: %s -> %s\n", prev, dir);
                    
                }
            }
        }
        keys.put(key, dir);
    }

    /**
     * Register the given directory, and all its sub-directories, with the
     * WatchService.
     */
    private void registerAll(final Path start) throws IOException {
        // register directory and sub-directories
        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                throws IOException
            {
                register(dir);
                return FileVisitResult.CONTINUE;
            }
        });
    }

    /**
     * Creates a WatchService and registers the given directory
     */
    WatchDir(Path dir, boolean recursive) throws IOException {
    	
        this.watcher = FileSystems.getDefault().newWatchService();
        
        this.keys = new HashMap<WatchKey,Path>();
        
        this.recursive = recursive;

        if (recursive) {
        	
            System.out.format("Scanning %s ...\n", dir);
            
            registerAll(dir);
            
            System.out.println("Done.");
            
        } else {
        	
            register(dir);
            
        }

        // enable trace after initial registration
        this.trace = true;
    }

    /**
     * Process all events for keys queued to the watcher
     */
    void processEvents() {
    	
        for (;;) {//这是个死循环

            // wait for key to be signalled
            WatchKey key;
            
            try {
                key = watcher.take();
            } catch (InterruptedException x) {
                return;
            }

            Path dir = keys.get(key);
            
            if (dir == null) {
            	
                System.err.println("WatchKey not recognized!!");
                
                continue;
            }

            for (WatchEvent<?> event: key.pollEvents()) {
            	
                WatchEvent.Kind kind = event.kind();

                // TBD - provide example of how OVERFLOW event is handled
                if (kind == OVERFLOW) {
                	
                    continue;
                    
                }

                // Context for directory entry event is the file name of entry
                WatchEvent<Path> ev = cast(event);
                Path name = ev.context();
                Path child = dir.resolve(name);

                // print out event
                System.out.format("%s: %s\n", event.kind().name(), child);

                // if directory is created, and watching recursively, then
                // register it and its sub-directories
                if (recursive && (kind == ENTRY_CREATE)) {
                    try {
                        if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                            registerAll(child);
                        }
                    } catch (IOException x) {
                        // ignore to keep sample readbale
                    }
                }
            }

            // reset key and remove from set if directory no longer accessible
            boolean valid = key.reset();
            if (!valid) {
                keys.remove(key);

                // all directories are inaccessible
                if (keys.isEmpty()) {
                    break;
                }
            }
        }
    }

    static void usage() {
        System.err.println("usage: java WatchDir [-r] dir");
        System.exit(-1);
    }
/******************************************
 * 使用方法,可以传入两个参数,
 * 第一个参数表示是否循环遍历该文件夹(可以不传),
 * 第二个参数代表要监控的文件路径。
 * 
 * @param args
 * @throws IOException
 */

    public static void main(String[] args) throws IOException {
        // parse arguments
        if (args.length == 0 || args.length > 2){
        	
            usage();
            
        }
        
        boolean recursive = false;
        
        int dirArg = 0;
        
        if (args[0].equals("-r")) {
        	
            if (args.length < 2){
            	
                usage();
                
            }
            
            recursive = true;
            
            dirArg++;
            
        }

        // register directory and process its events
        Path dir = Paths.get(args[dirArg]);
        
        new WatchDir(dir, recursive).processEvents();
    }
}

输出结果:

Scanning E:\work\ftp_file\download ...
Done.
ENTRY_CREATE: E:\work\ftp_file\download\New Text Document.txt
ENTRY_DELETE: E:\work\ftp_file\download\New Text Document.txt
ENTRY_CREATE: E:\work\ftp_file\download\11.txt
ENTRY_MODIFY: E:\work\ftp_file\download\11.txt
ENTRY_MODIFY: E:\work\ftp_file\download\11.txt
 

1.6 其它博文参考

http://codingjunkie.net/java-7-watchservice/

转载于:https://my.oschina.net/u/2308739/blog/688636

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java 1.7是一种编程语言和计算机平台,可用于开发各种应用程序和系统。它是Java语言的一个版本,于2011年发布。 ARM64是一种64位的处理器架构,通常在移动设备和嵌入式系统中使用。ARM64处理器提供更高的性能和更低的功耗。 Java 1.7可以在ARM64架构上运行,并针对该架构进行了优化。这意味着开发者可以使用Java 1.7版本来开发在ARM64设备上运行的应用程序。 Java 1.7为ARM64架构提供了许多功能和特性。其中包括对第三方库和API的支持,使开发者能够轻松集成和使用各种功能和服务。 对于开发者而言,使用Java 1.7 ARM64意味着他们可以编写能够在ARM64设备上高效运行的代码。这样可以充分利用ARM64架构的优势,提升应用程序的性能和响应速度。 另外,Java 1.7也提供了一些在ARM64平台上进行优化和测试的工具和库。这些工具和库可帮助开发者确保其应用程序在ARM64设备上的稳定性和兼容性。 总的来说,Java 1.7 ARM64是Java语言的一个特定版本,用于在ARM64设备上开发高性能和兼容性的应用程序。它为开发者提供了许多功能和优化,以便更好地利用ARM64架构的性能和能力。 ### 回答2: Java 1.7是Oracle公司发布的一种编程语言和计算机技术,它基于虚拟机的原理,能够实现跨平台的特性。ARM64是一种基于ARM架构的64位处理器指令集,具有更高的计算能力和更低的能耗。 Java 1.7版本在ARM64架构上的应用主要体现在移动设备和嵌入式平台上。由于ARM架构在移动设备上的普及度较高,Java 1.7版本的适配对于移动应用开发具有重要意义。Java 1.7在ARM64架构上的运行环境能够为开发者提供良好的编程体验和高性能的运行效果。 Java 1.7版本的ARM64支持了在嵌入式系统上的应用。嵌入式系统需要求低功耗、高效能和稳定性,Java 1.7版本的适配能够满足这些需求,为嵌入式系统的开发和运行提供了更好的选择。 虽然Java 1.7版本在ARM64架构上有一定的适配,但由于Java编程语言和虚拟机的特性,对于特定的应用场景和需求,可能会有更合适的选择。考虑到ARM64架构的特点,可能更推荐使用更新的Java版本或者其他更适合ARM64架构的编程语言。 综上所述,Java 1.7版本在ARM64架构上是可行的,并能够为移动设备和嵌入式系统提供高效、稳定和低功耗的解决方案。然而,对于特定的应用场景和需求,需要综合考虑Java版本、编程语言和架构特性,选择最合适的解决方案。 ### 回答3: Java 1.7Java编程语言的一个版本,而ARM64是一种基于ARM架构的64位处理器。 Java 1.7是Oracle公司在2011年发布的一个主要版本,它带来了很多新特性和改进。此版本的最重要的新功能之一是对动态语言的支持,通过引入了动态类型语言支持(JSR-292),Java 1.7使得Java能够更好地集成和与动态语言进行互操作。 ARM64是ARM体系结构的64位变种。ARM架构是一种常用的指令集架构,广泛应用于移动设备和嵌入式系统、单片机等领域。与传统的32位ARM架构相比,ARM64架构具有更大的寻址空间和更高的性能。 通过将Java 1.7与ARM64结合使用,可以将Java应用程序直接运行在基于ARM64架构的设备上。Java 1.7在ARM64架构上的执行效率可能会更高,因为ARM64具有更高的性能和更大的寻址空间。同时,Java 1.7的动态语言功能也可以为ARM64架构上的动态语言提供更好的支持。 总而言之,Java 1.7 ARM64结合可以为开发人员提供更好的工具和平台来开发和运行应用程序,特别是在基于ARM64架构的设备上。这对于移动设备、嵌入式系统和其他ARM64架构应用的开发和部署都具有重要意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值