8

这是参考Path#register方法。如果一个线程正在运行一个包含该方法的块并且另一个线程预先中断它。然后发现该方法清除了中断状态。

文档中没有提到它清除线程的中断状态。

复制

import java.io.*;
import java.nio.file.*;

import static java.nio.file.LinkOption.*;
import static java.nio.file.StandardWatchEventKinds.*;

import java.nio.file.attribute.*;

public class WatchDir {

    private final WatchService watcher;
    
    private void register(Path dir) throws IOException {
        // interrupt itself
        Thread.currentThread().interrupt();
        boolean before = Thread.currentThread().isInterrupted();
        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        boolean after = Thread.currentThread().isInterrupted();

        if (before) {
            if (!after) {
                System.out.println("--------------------BUG-------------------");
                System.out.format("Interrupt Status: true before making call to Path#register for folder folder: %s\n", dir);
                System.out.format("Interrupt Status: false after making call to Path#register for folder folder: %s\n", dir);
                System.out.println("The interrupt status was cleared by `register` (Unexpected Behavior).");
                System.exit(0);
            } else {
                System.out.println("Not a bug on your machine. The interrupt was not cleared after call to Path#register. Works as expected");
                System.out.println("Works well on your machine. Didn't work for me on Windows and Ubuntu with Java 7");
            }
        }
    }

    /**
     * Creates a WatchService and registers the given directory
     */
    WatchDir(Path dir) throws IOException {
        this.watcher = FileSystems.getDefault().newWatchService();
        register(dir);
    }
    
    public static void main(String[] args) throws Exception {
        // register directory and process its events
        Path dir = Paths.get(".");
        new WatchDir(dir);
    }
}

上面你可以观察到调用register函数后中断状态被清除。样本输出:

--------------------BUG-------------------
Interrupt Status: true before making call to Path#register for folder folder: .
Interrupt Status: false after making call to Path#register for folder folder: .
The interrupt status was cleared by `register` (Unexpected Behavior).

出现此问题是因为发现即使在请求关闭后服务仍处于活动状态。有任何想法吗?

编辑:事实证明它只发生在 Windows 和 Linux 中。Mac 的行为符合预期。我的操作系统:Win 7 64 位。JDK 1.7.0_11。还可以在以下位置找到:Ubuntu 14.04 Java 1.7.0_45-b18

4

3 回答 3

-1

问题可能在于catch块:

} catch (InterruptedException ex) {
  Logger.getLogger(WatchDir.class.getName()).log(Level.SEVERE, null, ex);
}

尝试添加

// Restore the interrupted status
Thread.currentThread().interrupt();

catch块中。

有关此主题的更多信息,请参阅“Java 理论与实践:处理 InterruptedException”一文

于 2013-01-28T08:19:37.163 回答
-1

一个人的interrupted旗帜Thread不是一个单独依靠的好领域。您应该同时监视interrupted标志并注意中断。

请参阅The Law of the Sabotaged Doorbell进行精彩讨论。

一个特别相关的引述来自这里(我的重点):

中断... 如果该线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法或 join()、join(long)、join( long, int)、sleep(long) 或 sleep(long, int) 方法,则其中断状态将被清除并收到 InterruptedException。

于 2013-01-28T09:47:02.023 回答
-2

这很简单......一旦你在同一个线程中引用了中断状态。它会被清除。

如果中断状态是从另一个线程引用的,它不会被清除

于 2013-02-03T07:44:46.233 回答