线程管理(四)操作线程的中断机制

声明:本文是《 Java 7 Concurrency Cookbook 》的第一章, 作者: Javier Fernández González 译者:郑玉婷 校对:欧振聪

操作线程的中断机制

在之前的指南里,你学习了如何中断执行线程和如何对Thread对象的中断控制。之前例子中的机制可以很容易中断的线程中使用。但是如果线程实现的是由复杂的算法分成的一些方法,或者它的方法有递归调用,那么我们可以用更好的机制来控制线程中断。为了这个Java提供了InterruptedException异常。当你检测到程序的中断并在run()方法内捕获,你可以抛这个异常。

在这个指南中, 我们将实现的线程会根据给定的名称在文件件和子文件夹里查找文件,这个将展示如何使用InterruptedException异常来控制线程的中断。

准备

指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。

怎么做呢

按照这些步骤来实现下面的例子::

1.   创建一个名为FileSearch的类,并一定要实现Runnable接口。

[code language=”java”]
public class FileSearch implements Runnable {
[/code]

2.   声明2个为private的属性,一个是为了我们要查找的文件名和另一个是为了初始文件夹。为这个类实现一个构造函数,并初始化这些属性。

[code language=”java”]
private String initPath;
private String fileName;
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}[/code]

3.   为FileSearch类实现run()方法。 它会检测fileName属性是不是路径,如果它是,就调用processDirectory()方法。这个方法会抛出一个InterruptedException异常,所以我们应该要捕获它。

[code language=”java”]
@Override
public void run() {
File file = new File(initPath);
if (file.isDirectory()) {
try {
directoryProcess(file);
} catch (InterruptedException e) {
System.out.printf("%s: The search has been interrupted",Thread.currentThread().getName());
}
}
}[/code]

4.   实现 directoryProcess()方法。这个方法会获取文件夹的文件和子文件夹并处理他们。对于每个路径,这个方法会传递路径作为参数来循环调用。对于每个文件,它会调用fileProcess()方法。处理完全部的文件和文件夹后,它会检查线程有没有被中断,在这个例子,会抛出一个InterruptedException异常。

[code language=”java”]
private void directoryProcess(File file) throws
InterruptedException {
File list[] = file.listFiles();
if (list != null) {
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
directoryProcess(list[i]);
} else {
fileProcess(list[i]);
}
}
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
[/code]

5.   实现 processFile()方法。这方法会比较文件的名字与我们要搜索的文件名。如果他们一样,就写一条信息到控制台。比较完后,线程会检查有没有被中断,在这里,它会抛出一个InterruptedException异常。

[code language=”java”]
private void fileProcess(File file) throws InterruptedException
{
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s\n",Thread.currentThread().getName() ,file.getAbsolutePath());
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
[/code]

6.   现在, 让我们来实现例子的主类吧。实现一个Main类并包含main()方法。

[code language=”java”]
public class Main {
public static void main(String[] args) {
[/code]

7.   创建并初始一个FileSearch类的对象和一个执行它的任务的线程。然后,开始执行线程。

[code language=”java”]
FileSearch searcher=new FileSearch("C:\\","autoexec.bat");
Thread thread=new Thread(searcher);
thread.start();
[/code]

8.   等10秒然后中断线程。

[code language=”java”]
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}[/code]

9.   运行例子并查看结果。

它是怎么工作的

下面的截图给出了例子的执行结果。你可以发现FileSearch对象是如何执行的,当它检测到它被中断时。请看裁图:

在这个例子, 我们使用Java异常来控制线程的中断。当你运行这个例子,程序开始浏览文件夹来检查他们是否含有那个文件。例如,如果你输入\b\c\d,那么程序会循环调用3次processDirectory()方法。当它检测到被中断时,它会抛出InterruptedException异常并继续执行方法,无论已经多少次循环调用。

更多

InterruptedException 异常是由一些与并发API有关的Java方法,如sleep()抛出的。

参见

  • 第一章,线程管理:线程的中断指南

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 线程管理(四)操作线程的中断机制

  • Trackback 关闭
  • 评论 (7)
    • fangqiang08
    • 2014/09/29 11:34上午

    Thread和 Thread.currentThread有什么区别啊?

    • Thread.currentThread 获取当前线程的实例。
      Thread 是个线程类。

    • hom_
    • 2015/03/11 11:28上午

    请问文章是不是没写全的?

    • shangshicc
    • 2015/10/22 7:08下午

    请问为什么在这个程序中用interrupted()方法判断是否中断,而不是用isInterrupted(),是有什么特殊的原因吗?

      • duqi
      • 2015/11/12 1:43下午

      我的理解是没有,暂时也不清楚如何选择

      • duqi
      • 2015/11/12 1:45下午

      想了下,应该是这个原因:interrupted()方法是静态方法,isInterrupted()是实例方法,在这个例子中FileSearch是实现了Runnable接口,因此只能通过Thread调用它的实例方法;如果使用extends(继承),让FileSearch继承Thread类的话,就可以使用isInterrupted()方法了

        • 雁过留影
        • 2018/01/10 3:59下午

        或者用Thread.currentThread()获取当前线程,再调用isInterrupted()来获取状态

return top