在Java中,如何使用jToggleButton停止使用WatchService for folders监视文件夹中文件的以下类型的线程

在Java中,如何使用jToggleButton停止使用WatchService for folders监视文件夹中文件的以下类型的线程,java,multithreading,concurrency,Java,Multithreading,Concurrency,我想通过使用jToggleButton停止以下方式生成的线程。线程用于监视文件夹中的文件。我尝试了很多,搜索了很多,但是没有成功。任何机构都可以提供帮助并提出任何解决方案来阻止像这样生成的线程。在Netbeans调试中,即使在按下jToggleButton之后,线程也会显示为活动线程。 我试过在不稳定的条件下停车, 仅供参考:我有一个JTOGLE按钮用于启动和停止线程 代码是由Netbeans生成的,因此还有一些额外的代码,但是您可能只关注jToggleActionListener中的代码和另一

我想通过使用jToggleButton停止以下方式生成的线程。线程用于监视文件夹中的文件。我尝试了很多,搜索了很多,但是没有成功。任何机构都可以提供帮助并提出任何解决方案来阻止像这样生成的线程。在Netbeans调试中,即使在按下jToggleButton之后,线程也会显示为活动线程。 我试过在不稳定的条件下停车, 仅供参考:我有一个JTOGLE按钮用于启动和停止线程

代码是由Netbeans生成的,因此还有一些额外的代码,但是您可能只关注jToggleActionListener中的代码和另一个类中的代码:谢谢您的帮助

package threadnames;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level; 
import java.util.logging.Logger;
public class NewJFrame extends javax.swing.JFrame {

    public NewJFrame() {
        initComponents();
    }
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jToggleButton1 = new javax.swing.JToggleButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jToggleButton1.setText("Stop");
    jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jToggleButton1ActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(84, 84, 84)
            .addComponent(jToggleButton1)
            .addContainerGap(142, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(25, 25, 25)
            .addComponent(jToggleButton1)
            .addContainerGap(28, Short.MAX_VALUE))
    );

    pack();
}// </editor-fold>                        

private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                               
    ExecutorService exec = Executors.newCachedThreadPool();
    if (this.jToggleButton1.isSelected()) {
        try {
            // TODO add your handling code here:
            Path home = Paths.get(System.getProperty("user.dir"));
            WatchService watcher;

            watcher = home.getFileSystem().newWatchService();

                home.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
            Runnable task = new FileWatch(watcher);
            exec.submit(task);
            boolean terminated;
            terminated = exec.awaitTermination(1, TimeUnit.SECONDS);

            if (terminated) {
                System.out.println("All tasks completed.");
            } else {
                System.out.println("Some tasks are still running.");
            }
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    } else {
        exec.shutdownNow();
    }
}                                              

public static void main(String args[]) {
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info    javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;


            }
        }
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |        javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(NewJFrame.class
                .getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new NewJFrame().setVisible(true);
        }
    });
}
// Variables declaration - do not modify                     
public javax.swing.JToggleButton jToggleButton1;
// End of variables declaration                   
}
下面是运行的另一个类:

package threadnames;

import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.Watchable;

final class FileWatch implements Runnable {

private final WatchService watcher;

FileWatch(WatchService watcher) {
    this.watcher = watcher;
}

@Override
public void run() {
    while (!Thread.currentThread().isInterrupted()) {
        WatchKey key;
        try {
            key = watcher.take();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            break;
        }
        Watchable dir = key.watchable();
        System.out.println(dir);
        for (WatchEvent<?> evt : key.pollEvents()) {
            System.out.println("   " + evt.context());
        }
    }
}
}
有一个Thread.stop方法,但它一直是,因为它不安全

您可以修改一些变量来指示目标线程应该停止运行,而不是使用不推荐使用的方法。

您可以在run方法中使用一些标志来检查是否退出该方法,通过这种方式您可以间接退出run方法。 目前不建议使用任何其他方法停止线程。 参见

一种方法是使用stop方法,将volatile boolean设置为true

如果线程可能被阻塞,您可以安排中断它,但当然这不能保证中断线程,因为它可能没有被阻塞,只是很忙

public class HelloRunnable implements Runnable {
  private volatile boolean stop = false;
  private volatile Thread thread = null;

  public void run() {
    thread = Thread.currentThread();
    if (!stop) {
      System.out.println("Hello from a thread!");
    }
  }

  public void stop() {
    stop = true;
    if ( thread != null ) {
      thread.interrupt();
    }
  }

  public static void main(String args[]) {
    for (int i = 0; i < 5; i++) {
      HelloRunnable hr = new HelloRunnable();
      new Thread(hr).start();
      hr.stop();
    }
  }
}
如果使用或,最后一种技术也应该有效

如果线程忙于大多数IO进程,它还应该中断线程。

使用线程中断状态 使用线程的中断状态终止循环。这比您自己创建的标志要好,因为它使您的任务可用于ExecutorService;您可以在提交某项特定任务时取消该任务,也可以使用shutdownNow中断所有任务

除非您的任务正在您自己创建和管理的线程中运行,否则在检测到中断后重新断言中断状态是最安全的,这样您的调用者也可以处理它。换句话说,所有线程和任务都需要有一个定义的中断策略,并相应地使用

实例 下面是一个示例可运行任务,使用:

因为FileWatch任务正确地支持中断,所以您将看到此测试显示在调用Shutdownow后所有任务都很快完成。如果将使用其他终止方法的任务添加到ExecutorService,您将看到它们继续运行

有问题的代码 目前的代码有几个问题。下面是对jToggleButton1ActionPerformed事件处理程序的分析,按下按钮时,Swing事件调度线程将调用该事件处理程序

When the button is pressed, create a new ExecutorService as a local variable. If toggle selected, submit a file watching task to the executor, and block the EDT for 1 second, or until the executor is shutdown. Otherwise, shutdown the newly-created executor. Discard reference to the executor.
另外,对于您在这里的使用,一个newSingleThreadedExecutor就足够了。

为什么?这些线程只是打印语句,然后结束。为什么/何时结束它们?在您尝试停止它们时,大多数线程都已完成。你为什么试图停止那些会自动停止的线程?我真的不明白-你想停止属于某个特定类的线程吗?你想通过扩展runnable并创建一个新的Thread对象来禁用启动线程吗,您到底想“停止”什么?在控制台上打印后,线程应该自动停止。只需使用Threadinterrupt而不是手动停止标志:或者,在提供的示例中,您可以只等待几微秒…:@SteveBenett-不比OP多。这种方法的问题是ExecutorService只使用线程中断来停止运行任务。与其创建非标准API来设置新标志,不如让您的任务检查中断。当然,您的任务可能需要执行一些阻塞操作,这些操作设计不当,无法支持中断或超时。这没有什么帮助。@OldCurmudgeon,现在请检查问题并提出任何解决方案。@AhmadullahAchakzai-这个解决方案在您的案例中仍然有效。在运行开始时记录线程,并在需要停止时中断该线程。感谢@erickson的帮助。我在我的应用程序中实现了您的解决方案,但它在那里不起作用,在我自己尝试的地方,它确实起作用。首先,让我解释一下,在我的应用程序中,监视5个文件夹的踏板是在按下jToggleButton之后创建的,比如:通过调用Runnable task=new filewatcherseprateforeachfolder,我在按下jToggleButten时在jToggleButten中实现了exec.shutdown。尽管调用exec.shutdown,线程仍然不会终止;此外,在我的应用程序中,WatchService在知道监视文件夹中有一个新文件时,会生成另一个线程来处理该文件!这意味着也有子线程,但是当ru
我用jToggleButton尝试了你的代码,你的代码也不起作用。我的意思是线程仍然在运行,执行器没有关闭!请给我一个建议!非常感谢您的合作@AhmadullahAchakzai您使用的是关机,还是立即关机?现在只有关机才能取消正在运行的任务。您不应该每个位置都需要一个线程,而是每个观察者需要一个线程,每个观察者应该服务于一个完整的文件系统。您的按钮应该只向现有的WatchService注册路径,该WatchService正在被另一个线程轮询。谢谢,我已经在您上面建议的jToggleButton代码中使用了Shutdownow。我用了你的密码。我试图将代码粘贴到这里,但这比这里允许的字符长了一点。你能告诉我如何发送你的代码,因为我是新在这个论坛!
final class FileWatch implements Runnable {
  private final WatchService watcher;
  FileWatch(WatchService watcher) { this.watcher = watcher; }
  @Override
  public void run()
  {
    while (!Thread.currentThread().isInterrupted()) {
      WatchKey key;
      try {
        key = watcher.take();
      }
      catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
        break;
      }
      Watchable dir = key.watchable();
      System.out.println(dir);
      for (WatchEvent<?> evt : key.pollEvents()) {
        System.out.println("   " + evt.context());
      }
    }
  }
}
public static void main(String... argv)
  throws Exception
{
  Path home = Paths.get(System.getProperty("user.home"));
  WatchService watcher = home.getFileSystem().newWatchService();
  home.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.OVERFLOW);
  Runnable task = new FileWatch(watcher);
  ExecutorService exec = Executors.newCachedThreadPool();
  exec.submit(task);
  Thread.sleep(3000);
  exec.shutdownNow();
  boolean terminated = exec.awaitTermination(1, TimeUnit.SECONDS);
  if (terminated)
    System.out.println("All tasks completed.");
  else
    System.out.println("Some tasks are still running.");
}
When the button is pressed, create a new ExecutorService as a local variable. If toggle selected, submit a file watching task to the executor, and block the EDT for 1 second, or until the executor is shutdown. Otherwise, shutdown the newly-created executor. Discard reference to the executor. When the button is pressed, If toggle selected, create a new executor service and assign it to a member variable, and submit a file watching task to the service. Otherwise, shutdown the executor, and wait for the service to terminate.