当前位置: 首页 > 面试题库 >

如何通过使用jToggleButton停止Java中用于监视文件夹中文件的Java中以下类型的线程

商兴朝
2023-03-14
问题内容

我想通过使用jToggleButton停止以以下方式生成的线程。线程用于监视文件夹中的文件。我尝试了很多,并进行了大量搜索,但未成功。任何机构都可以提供帮助并建议任何解决方案来停止生成的线程。即使按下jToggleButton,这些线程在Netbeans调试中仍显示为活动状态。我尝试了用于停止的易失性条件,仅供参考:我有一个jToggle按钮,用于启动和停止线程。

该代码是由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                   
}

这是run()的另一个类:

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());
        }
    }
}
}

问题答案:

使用线程的中断状态终止循环。这比您创建自己的标志更好,因为它使您的任务可与一起使用ExecutorService;您可以通过Future提交时收到的特定任务取消特定任务,也可以使用中断所有任务shutdownNow()

除非您的任务在创建和管理的线程中运行,否则在检测到中断后重新声明中断状态是最安全的,以便调用者也可以处理它。换句话说,所有线程和任务都必须具有定义的中断策略并相应地使用。

这是使用的示例Runnable任务WatchService

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.");
}

由于FileWatch任务正确支持中断,因此您将看到此测试显示shutdownNow()调用后不久所有任务都已完成。如果您将使用其他终止方法的任务添加到中ExecutorService,则会看到它们继续运行。

有问题的代码

目前的代码存在两个问题。这是jToggleButton1ActionPerformed()事件处理程序的分析,按下按钮时,该事件处理程序由Swing事件调度线程(
EDT )调用。

当按下按钮时,
  创建一个新的ExecutorService作为局部变量。
  如果选择切换,
    向执行者提交文件监视任务,以及
    阻塞EDT 1秒钟,或者直到执行程序关闭。
  除此以外,
    关闭新创建的执行程序。
  放弃对执行程序的引用。

第一个问题是,由于执行程序服务永远不会存储在局部变量之外的任何地方,因此一旦该方法退出,对该特定实例的引用将永远丢失,并且无法对其进行调用shutdownNow()

第二个问题是,如果确实要阻止EDT(可能不是一个好主意)直到执行程序终止,则应在调用之后shutdownNow()(在“
else”子句中,未选中toggle时)执行此操作,而不是在提交任务之后执行。再次查看上面的示例,您将看到我仅在关闭执行程序后才等待终止。

将ExecutorService变量从方法中吊起,并使其成为类的成员变量。这将允许切换按钮处理程序访问 同一个实例
ExecutorService,并关闭它。然后,将等待终止移至未选择的切换分支。

这是应该的流程:

当按下按钮时,
  如果选择切换,
    创建一个新的执行程序服务并将其分配给成员变量,然后
    向服务提交文件监视任务。
  除此以外,
    关闭执行程序,并
    等待服务终止。

另外,只要您在这里使用,a newSingleThreadedExecutor()就足够了。



 类似资料:
  • 我试图构建一个应用程序,监视文件夹及其子文件夹,以检测文件的创建或修改。要观看的文件总数将日益增加。 我曾尝试使用java nio WatchService和apache常见的FileAlteration观察者。WatchService有时会在WatchKey被获取之后和重置之前发生文件创建/修改时丢失事件。由于FileAlterationeller是基于轮询的,因此当文件计数增加时性能也会下降。

  • 问题内容: 我在Sun上阅读了有关JAR文件的Java教程,但是仍然找不到解决我问题的方法。我需要使用一个名为jtwitter.jar的jar文件中的类,我下载了该文件并尝试执行该文件(昨天我发现可以通过双击来执行.jar文件),而Vista却给我一个错误提示:无法从[路径] /jtwitter.jar加载Main-Class Manifest属性。 编码.jar文件的人要我将其导入,但是在哪里将

  • 我是java新手,我在VSCODE上编码。我创建2.java文件,如下图所示: 这些是每个文件: Main.java:

  • 我有一个程序,当你点击“开始”时移动鼠标光标 单击“开始”,我创建了一个新线程,光标开始移动。当我单击“暂停”时,即使变量设置为false,光标仍会移动。 我不明白为什么当我点击“暂停”时,鼠标会一直移动,即使移动设置为false。 有人能看出我哪里出了问题,或者是否有更好的方法来解决这个问题吗?

  • 我正在使用Chrome编写一些Selenium WebDriver和AutoIt Java测试。当我在Chrome中下载一个文件时,它会自动下载到我电脑上的downloads文件夹中。我正在一个存储库上与多个其他用户共享这个代码项目,因此我不想将我的下载文件夹与我的特定用户名硬编码在其中。 我的意思是假设我电脑上的用户名是“Eamon”。我的机器上的下载文件夹是“C:\Users\Eamon\do

  • 问题内容: 我正在尝试使用JFileChooser保存图像。我只希望用户能够将图像另存为jpg。但是,如果他们不输入.jpg,它将不会另存为图像。是否可以以某种方式将“ .jpg”附加到文件末尾? 在将字符串添加到文件时不起作用。 问题答案: 完成后,为什么不将转换为并创建一个新的呢? 请记住,如果已经存在,则不需要添加。