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 は期待どおりに動作します。私の OS: 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

aのinterruptedフラグは、Thread単独で頼りにするのに適したフィールドではありません。interruptedフラグを監視し、割り込みを監視する必要があります。

優れた議論については、The Law of the Sabotaged Doorbellを参照してください。

特に適切な引用はここから来ています(私の強調):

interrupt ... 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

それは簡単です..同じスレッドでinterruptionステータス内部を参照したら。クリアされます。

中断ステータスが別のスレッドから参照された場合、それはクリアされません

于 2013-02-03T07:44:46.233 に答える