如何使用jToggleButton在Java中停止以下类型的线程,用于使用WatchService查看文件夹的文件夹 [英] How to stop threads of following type in Java used for watching folders for files using WatchService for folders by using jToggleButton

查看:115
本文介绍了如何使用jToggleButton在Java中停止以下类型的线程,用于使用WatchService查看文件夹的文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过使用jToggleButton来停止以下面的方式生成的线程。线程用于监视文件的文件夹。我尝试了很多,并搜索了很多,但没有成功。可以任何身体帮助并建议任何解决方案来阻止生成的线程。即使在按下jToggleButton之后,线程也会在Netbeans调试中显示为活动状态。
我已经尝试了停止的波动条件,
FYI:我有一个jToggle按钮用于启动和停止线程。

I would like to stop threads generated in the following manner by using jToggleButton. The threads are used for watching folders for files. I tried a lot, and searched alot, but am not successful. Could any body help and suggest any solution to stop threads generated like. The threads are shown alive in Netbeans debugging even after pressing the jToggleButton. I have tried the volatile condition for stopping, FYI: I have a jToggle button for starting and stopping the threads.

代码生成通过Netbeans,所以有一些额外的代码,但你可能只关注jToggleActionListener中的代码和另一个类中的代码:感谢您的帮助。

The code is generated by Netbeans, so there is some extra code, but you may only focus on the code inside the jToggleActionListener and the code in another class: Thanks for your help.

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():

Here is the other class for the 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()

Use thread interruption status

Use the interruption state of the thread to terminate a loop. This is better than a flag you create yourself because it makes your task usable with an ExecutorService; you can cancel a specific task through the Future you received when it is submitted, or you can interrupt all tasks with shutdownNow().

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

Unless your task is running in a thread you create and manage yourself, it's safest to re-assert the interruption status after detecting interruption, so that your caller can deal with it too. In other words, all threads and tasks need to have a defined interruption policy and to be used accordingly.

这是使用 Runnable 任务的示例WatchService.htmlrel =nofollow> WatchService

Here's an example Runnable task using 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());
      }
    }
  }
}

这是如何使用这样的服务:

Here's how you could use such a service:

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 ,您将看到它们继续运行。

Because the FileWatch task correctly supports interruption, you will see that this test shows all tasks are completed soon after shutdownNow() is called. If you add tasks that use some other termination method to the ExecutorService, you will see that they continue to run.

目前代码存在一些问题。这里是对 jToggleButton1ActionPerformed()事件处理程序的分析,当按下按钮时,该处理程序由Swing事件调度线程( EDT )调用。 / p>

There are a couple of problems with the code as it stands currently. Here's analysis of the jToggleButton1ActionPerformed() event handler, which is invoked by the Swing Event Dispatch Thread (the EDT) when the button is pressed.


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.

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

The first problem is that since the executor service is never stored anywhere but a local variable, once that method exits, a reference to that particular instance is lost forever, and there's no way to invoke shutdownNow() on it.

第二个问题是,如果真的想要阻止EDT(可能不是一个好主意),直到执行程序终止,你应该在调用 shutdownNow()(在else子句中,取消选择切换时),而不是在提交任务之后。再看看上面的例子,你会看到我在关闭执行程序后等待终止。

The second problem is that, if really want block the EDT (probably not a good idea) until the executor terminates, you should do it after invoking shutdownNow() (in your "else" clause, when toggle is unselected), not after submitting the task. Look at my example above again and you'll see that I await termination only after I shutdown the executor.

将ExecutorService变量从方法中提升出来,并使其变为你班级的成员变量。这将允许切换按钮处理程序访问 ExecutorService 相同的实例并将其关闭。然后,将等待终止移动到未选择的切换分支。

Hoist the ExecutorService variable out of the method, and make it a member variable of your class. This will allow the toggle button handler to access the same instance of the ExecutorService and shut it down. Then, move the wait for termination to the unselected toggle branch.

这是流程应该是:


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.

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

Also, for your use here, a newSingleThreadedExecutor() would suffice.

这篇关于如何使用jToggleButton在Java中停止以下类型的线程,用于使用WatchService查看文件夹的文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆