使用线程的中断状态终止循环。这比您创建自己的标志更好,因为它使您的任务可与一起使用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()
就足够了。