How to terminate continuous thread that detects new file

This is my first foray into both WatchService and multithreading.

I have an application that needs to detect when an external device issues a prompt for the user to do something. The prompt is delivered by way of an XML file dropped into a specific folder. The file is always titled "PRM.xml" and will overwrite previous PRM files if they exist. To prevent re-displaying old prompts, my code deletes the PRM file once displayed.

The application is user-interactive, so it is always listening for a PRM.xml in a background thread while the user is performing other activities on the main thread.

The problem is that when the user wants to end his session in the main thread (by typing sentinel "zzz"), the listening thread won't end, and the application only terminates if another event happens in the folder being monitored.

How do I force the background listening thread to quit when the user directs the main thread to terminate? (I hope I have included enough code to get a good response.)

// Method 'run' contains code to be executed in the thread
public void run() {

  try {
     // initiate new watch service to watch for new prompts
     WatchService ws = dirToWatch.getFileSystem().newWatchService();
     dirToWatch.register(ws, ENTRY_CREATE);

     // monitor directory continuously until main program thread ends
     while (!SmartTill.stCom.equals("ZZZ")) {

        // get new directory events
        WatchKey wk = ws.take();

        // loop through all retrieved events
        for (WatchEvent<?> event : wk.pollEvents()) {

           if (event.context().toString().endsWith(fileToDetect)) {
              System.out.println("DEBUG: Display Prompt, Delete PRM.");
              // ...call to "displayPrompt" method goes here...
              delFile(Paths.get(dirToWatch + fileToDetect));
           }// end if
        }// end for

     // reset the key (erase list of events)
     System.out.println("Key has been " + 
             (wk.reset() ? "reset." : "unregistered."));
     }// end while
  }// end try
  catch(Exception e){}
}// end run

How do I force the background listening thread to quit when the user directs the main thread to terminate?

You should interrupt the thread. The WatchService.take() method throws InterruptedException. This means that when the main thread is done, it can interrupt the watch service thread. This will cause the take() method to throw an InterruptedException which gives the watch thread a chance to clean up and quit the while loop and then return from the run() method.

Thread watchThread = new Thread(new WatchRunnable());
watchThread.start();
// ...
// when the main thread wants the program to stop, it just interrupts the thread
watchThread.interrupt();
// although not necessary, main thread may wait for the watch-thread to finish
watchThread.join();

When you catch InterruptedException, it is always a good pattern to re-interrupt the thread so that callers can also use the interrupt status:

WatchKey wk;
try {
   wk = ws.take();
} catch (InterruptedException ie) {
   // always recommended
   Thread.currentThread().interrupt();
   // leave the loop or maybe return from run()
   break;
}

It is important to note that interrupting a thread is not some magical call. It sets an interrupt flag on the thread which causes certain methods which explicitly throw InterruptedException to throw. If other parts of your code want to see if the thread has been interrupted, they should do something like the following.

if (Thread.currentThread().isInterrupted()) {
    // clean up and exit the thread...
    break;
}

Another solution would just be make the watcher thread be a daemon thread. This will mean that when the main thread finishes, the JVM will quit immediately and not wait for the watchThread to finish. It's not as good as the interrupt above because it might stop the watchThread right in the middle of it doing some important file IO.

Thread watchThread = new Thread(new WatchRunnable());
watchThread.setDaemon(true);
watchThread.start();

How to terminate continuous thread that detects new file, How to terminate continuous thread that detects new file. 发布于 2020-05-03 05: 51:11. This is my first foray into both WatchService and multithreading. I have an � CancellationTokenSource cts = new CancellationTokenSource(); Console.WriteLine("Press 'C' to terminate the application "); // Allow the UI thread to capture the token source, so that it // can issue the cancel command.


I had the same issue and i found this solution to be working,

the solution was to override the interrupt method (your class should extend Thread instead of Runnable) and close the watchService from there, this will throw ClosedWatchServiceException in your take() method, so you have to catch this exception

Override interrupt

@Override
public void interrupt() {
    super.interrupt();
    System.out.println("Interupt is called");
    try {

            watcher.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Handling exception

try {
            key = watcher.take();
        } catch (InterruptedException x) {
            System.out.println("take() is interrupted");
            Thread.currentThread().interrupt();
            return;
        } catch (ClosedWatchServiceException e) {
            System.out.println(" take is killed from closedException");
            return;
        }

Main Thread

public static void main(String[] args) throws InterruptedException {
    WatchDir watchDir = new WatchDir(path);
    Thread.currentThread().sleep(1000);
    watchDir.shutDown();
    watchDir.interrupt();
    watchDir.join();
    System.out.println("the WatchDir thread is killed");
}

Watching a Directory for Changes (The Java™ Tutorials > Essential , See JDK Release Notes for information about new features, enhancements, and removed or jEdit Dialog Box Showing That a Modified File Is Detected Close the service: The watch service exits when either the thread exits or when it is� In C#, a thread can be terminated using Abort () method. Abort () throws ThreadAbortException to the thread in which it called. Due to this exception, the thread is terminated. There are two methods in the overload list of Thread.Abort Method as follows: Abort ()


Try adding a shutdown hook to the main thread, so that when the main application exits, you can properly terminate the listening thread as well.

Changes to be done

From your code, the following changes need to be done:

  1. Allow WatchService to be closed from main thread
  2. Add a new thread to the Shutdown Hook so that it will close the WatchService on application shutdown.
1. Making WatchService closeable

The WatchService should be allowed to be closed in the class that implements the listening thread.

public void stopThread() {
    try {
        System.out.println("closing the ws");
        ws.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
2. Make WatchService Close on Application Shutdown

In the main thread, add a shutdown hook so that when the application closes, it will call the stopThread() method of the listening thread class.

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(listenThreadObj) {
    public void run() {
        listenThreadObj.stopThread();
    }
}));
Sample Code
Listening Thread
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class ListeningThread implements Runnable {

    WatchService ws;

    public ListeningThread() {
        try {
            ws = FileSystems.getDefault().newWatchService();
            Path watchPath = FileSystems.getDefault().getPath("<path_to_directory>");
            watchPath.register(ws, StandardWatchEventKinds.ENTRY_CREATE);
            watchPath.register(ws, StandardWatchEventKinds.ENTRY_MODIFY);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        WatchKey wk;
        try {
            while ((wk = ws.take()) != null) {
                for (WatchEvent<?> we : wk.pollEvents()) {
                    System.out.println(we.kind());
                }
            }
        } catch (InterruptedException e) {
            System.out.println("WatchService closed");
            e.printStackTrace();
        }
    }

    public void stopThread() {
        try {
            System.out.println("closing the ws");
            ws.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Main Thread
import java.util.Scanner;

public class MainThread {
    public static void addShutdownHook(ListeningThread thread) {
        Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownCleaner(thread)));
    }

    public static void main(String[] args) {
        ListeningThread lt = new ListeningThread();
        Thread listenThread = new Thread(lt, "ListenThread");
        addShutdownHook(lt);
        listenThread.start();

        Scanner sc = new Scanner(System.in);
        sc.next();
        System.exit(0);
    }

    private static class ShutdownCleaner implements Runnable {
        private ListeningThread listenerThread;

        public ShutdownCleaner(ListeningThread lt) {
            this.listenerThread = lt;
        }

        @Override
        public void run() {
            // Shutdown runs
            if (listenerThread != null) {
                listenerThread.stopThread();
            }
        }
    }
}

When the main thread closes, it will run the ShutdownCleaner thread.

FileSystemWatcher Class (System.IO), Listens to the file system change notifications and raises events when a directory, or file in a directory, When a file is renamed, the old and new paths print to the console. GetCommandLineArgs(); // If a directory is not specified, exit program. if (args.Length Running FileSystemWatcher on Windows 98 is not supported. Therefore there is no direct function to close the thread. But we can notify the thread to exit and we can implement out thread in a such a way that after some interval or at some checkpoints it should check, if I am requested to exit or not. If yes then it should exit gracefully , by releasing all the resources. Stopping a Thread using std::future<>


[Solved] File system watcher sometimes does not pick up files , up and process create new xml file and place it in destination folder. 3) Existing files: FileSystemWatcher will not tell you about files that My second thread is then running in a loop, to do some work every (If reset fails, an error is logged, and this thread will exit because there's no point continuing). Normally, join waits only for a certain thread to terminate (for a specified amount of time, if any) without doing anything to cause that termination. In this recipe, however, join sets the stop event object before delegating the rest of its operation to the normal (base class) join method.


Start and stop a thread in Python, Once started, threads run independently until the target function returns. Code #2 : Querying a thread instance to see if it's still running. Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.


Nope. CopyFile should do its useful stuff and terminate. If it must run continuosly (e.g. copying an infinite list of files) then it should implement an infinite loop.