1.5 线程中断的控制

通过上一节,你已经学会了如何去中断执行中的线程,也学会了如何在线程对象中去控制这个中断。上一个例子中使用的机制,可以使用在线程很容易被中断的情况下。但是,如果线程实现了复杂的算法并且分布在几个方法中,或者线程里有递归调用的方法,我们就得使用一个更好的机制来控制线程的中断。为了达到这个目的,Java提供了InterruptedException异常。当检查到线程中断的时候,就抛出这个异常,然后在run()中捕获并处理这个异常。

在本节中,我们将实现线程类来完成下面的内容,它在一个文件夹及其子文件夹中寻找一个指定的文件。这个范例将示范如何用InterruptedException异常来控制线程的中断。

准备工作
本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其他的IDE(比如NetBeans),都可以打开这个IDE并且创建一个新的Java工程。

范例实现
按照接下来的步骤实现本节的范例。

1.创建一个名为FileSearch的类,并且实现Runnable接口。
``
public class FileSearch implements Runnable {``
2.声明两个私有属性,一个是我们将要查找的文件名称,另一个是初始文件夹。实现这个类的构造器,用来初始化这两个属性。

private String initPath;
private String fileName;
public FileSearch(String initPath, String fileName) {
  this.initPath = initPath;
  this.fileName = fileName;
}```
3.在FileSearch中实现run()方法。它将检查fileName属性是不是一个目录,如果是,就调用processDirectory()方法。processDirectory()方法会抛出InterruptedException异常,因此必须捕获并处理这个异常。

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

}
}`4.实现directoryProcess()方法,这个方法会获取一个文件夹里的所有文件和子文件夹,并进行处理。对于每一个目录,这个方法将递归调用,并且用相应目录名作为传入参数。对于每个文件,这个方法将调用fileProcess()方法。处理完所有的文件和文件夹后,这个方法将检查线程是不是被中断了,如果是,就抛出InterruptedException异常。

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();
   }
}```
5.实现processFile()方法。这个方法将比较当前文件的文件名和要查找的文件名,如果文件名匹配,就将信息打印到控制台。做完比较后,线程将检查是不是被中断了,如果是,它将抛出InterruptedException异常。

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

}
}`6.现在,我们实现这个范例的主类。实现一个包含main()方法的Main类。

public class Main {
  public static void main(String[] args) {```
7.创建FileSearch类的一个对象,并用它作为传入参数来创建一个线程对象,然后启动线程执行任务。

FileSearch searcher=new FileSearch("C:\","autoexec.bat");
Thread thread=new Thread(searcher);
thread.start();`8.等待10秒钟,然后中断线程。

try {
      TimeUnit.SECONDS.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    thread.interrupt();
}```
9.运行这个范例并查看结果。

工作原理
下面的截屏记录了范例的运行结果。你可以看到当FileSearch对象检测到它被中断之后就结束了运行。
<div style="text-align: center"><img src="https://yqfile.alicdn.com/d6a979ab3224d3bda1841cb6961f84e870d48de9.png" width="" height="">
</div>

在本范例中,我们使用了Java异常来控制线程的中断。当运行这个范例时,程序将进入文件夹查找是否包含指定的文件。例如,如果要查找的文件夹目录结构是\b\c\d,这个程序将递归调用processDirectory()方法3次。不管递归调用了多少次,只要线程检测到它已经被中断了,就会立即抛出InterruptedException异常,然后继续执行run()方法。

更多信息