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.实现run()方法,该方法检查fileName是否一个路径名称。如果是,则调用directoryProcess()方法进行处理。directoryProcess()方法会抛出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());

    }

}

}

原文中,提到的方法名称为processDirectory()。但是,根据下文的程序,属于笔误。故改正。
4.实现directoryProcess()方法。该方法读取指定目录下的所有文件以及子目录再进行处理。对于每一个目录,该方法进行一个递归调用,来处理参数指定的目录。对于每一个文件,该方法会调用fileProcess()方法。在处理完所有的目录以及文件后,该方法会检查线程是否被中断,这是抛出一个InterruptedException异常。代码如下:

/**

  • 处理一个目录

    *

  • @param file 需要处理的目录

  • @throws InterruptedException

    */

private void directoryProcess(File file) throws InterruptedException {

File[] list = file.listFiles();

if (null != list) {

    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.实现fileProcess()方法,该方法会比较正在处理的文件和需要查找的文件名。如果文件名称相等,则在控制台打印出一条信息。然后,线程检查是否被中断,如果是,则抛出InterruptedException异常。代码如下:

/**

  • 处理的文件

    *

  • @param file 需要处理的文件

  • @throws 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()方法。代码如下:

public class Main {

public static void main(String[] args) {

7.创建并初始化FileSearch对象,然后创建一个Thread对象,来执行该任务。然后,启动该线程。代码如下:

FileSearch fileSearch = new FileSearch(“C:\”, “autoexec.bat”);

Thread thread = new Thread(fileSearch);

thread.start();

8.等待十秒钟,然后中断线程。代码如下:

try {

TimeUnit.SECONDS.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}
thread.interrupt();
9.执行该示例,查看结果。

知其所以然

下面是线程执行的结果。从输出中可以看出,当FileSearch检测到被中断后,如何中止线程执行的。

Thread-0 : C:\autoexec.bat

Thread-0: The search has been interrupted

本示例中,我们使用Java的异常来控制线程的中断。当你运行示例时,程序会检测指定目录及其子目录是否包含目标文件。例如,如果输入\b\c\d,程序将会递归调用三次directoryProcess()方法。当线程检测到其被中断,则会抛出InterruptedException异常,无论执行多少次递归调用,程序都会开始执行run()方法。

永无止境

InterruptedException异常一般由Java并发API,例如sleep()方法,抛出。

小有所成

FileSearch类的完整代码

package com.diguage.books.concurrencycookbook.chapter1.recipe4;
import java.io.File;

/**
* Date: 2013-09-18
* Time: 18:21
*/
public class FileSearch implements Runnable {
private String initPath;
private String fileName;

/**
 * 初始化构造函数
 *
 * @param initPath 需要进行查找的目录
 * @param fileName 需要查找的文件名称
 */
public FileSearch(String initPath, String fileName) {
    this.initPath = initPath;
    this.fileName = fileName;
}

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

/**
 * 处理一个目录
 *
 * @param file 需要处理的目录
 * @throws InterruptedException
 */
private void directoryProcess(File file) throws InterruptedException {
    File[] list = file.listFiles();
    if (null != list) {
        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();
    }
}

/**
 * 处理的文件
 *
 * @param file 需要处理的文件
 * @throws 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();
    }
}

}
Main类的完整代码

package com.diguage.books.concurrencycookbook.chapter1.recipe4;
import java.util.concurrent.TimeUnit;

/**
 * Date: 2013-09-18
 * Time: 19:28
 */
public class Main {
    public static void main(String[] args) {
        FileSearch fileSearch = new FileSearch("C:\\", "autoexec.bat");
        Thread thread = new Thread(fileSearch);
        thread.start();

        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread.interrupt();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值