Java并发编程示例(四):可控的线程中断

 更新时间:2014年12月05日 10:05:52   投稿:junjie  
这篇文章主要介绍了Java并发编程示例(四):可控的线程中断,在本节,我们将使用一个线程查找指定目录及其子目录下文件来演示通过使用InterruptedException异常控制线程中断,需要的朋友可以参考下

在上一节“线程中断”中,我们讲解了如何中断一个正在执行的线程以及为了中断线程,我们必须对Thread动点什么手脚。一般情况下,我们可以使用上一节介绍的中断机制。但是,如果线程实现了一个分配到多个方法中的复杂算法,或者方法调用中有一个递归调用,我们应该使用更好的方式来控制线程的中断。为此,Java提供了InterruptedException异常。当检测到中断请求时,可以抛出此异常,并且在run()方法中捕获。

在本节,我们将使用一个线程查找指定目录及其子目录下文件来演示通过使用InterruptedException异常控制线程中断。

知其然

按照下面所示步骤,实现示例程序。

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()方法,抛出。

拿来主义

本文是从 《Java 7 Concurrency Cookbook》 (D瓜哥窃译为 《Java7并发示例集》 )翻译而来,仅作为学习资料使用。没有授权,不得用于任何商业行为。

小有所成

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

相关文章

  • SpringBoot项目部署到腾讯云的实现步骤

    SpringBoot项目部署到腾讯云的实现步骤

    本文主要介绍了SpringBoot项目部署到腾讯云的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Java实现文件批量重命名,移动和删除

    Java实现文件批量重命名,移动和删除

    这篇文章主要为大家介绍了如何利用Java语言实现批量重命名,批量移动文件,批量删除tmp文件等功能,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-08-08
  • SpringBoot自动配置源码深入刨析讲解

    SpringBoot自动配置源码深入刨析讲解

    这篇文章主要介绍了SpringBoot自动配置原理分析,SpringBoot是我们经常使用的框架,那么你能不能针对SpringBoot实现自动配置做一个详细的介绍。如果可以的话,能不能画一下实现自动配置的流程图。牵扯到哪些关键类,以及哪些关键点
    2022-09-09
  • Java判断2个List集合是否相等(不考虑元素的顺序)

    Java判断2个List集合是否相等(不考虑元素的顺序)

    今天小编就为大家分享一篇关于Java判断2个List集合是否相等(不考虑元素的顺序)的文章,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • Spring Bean名称不会被代理的命名技巧

    Spring Bean名称不会被代理的命名技巧

    Spring Bean一些使用小细节就是在不断的源码探索中逐步发现的,今天就来和小伙伴们聊一下通过 beanName 的设置,可以让一个 bean 拒绝被代理
    2023-11-11
  • java实现日历效果的示例代码

    java实现日历效果的示例代码

    这篇文章主要为大家详细介绍了如何使用java实现打印某年全部的日历信息,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以学习一下
    2023-12-12
  • Java基础:彻底搞懂java多线程

    Java基础:彻底搞懂java多线程

    篇文章主要介绍了Java多线程的相关资料,帮助大家更好的理解和学习Java线程相关知识,感兴趣的朋友可以了解下,希望能给你带来帮助
    2021-08-08
  • 使用Java计算屏幕的PPI的方法详解

    使用Java计算屏幕的PPI的方法详解

    在现代电子设备中,屏幕的分辨率和显示效果是用户非常关注的一个指标,PPI(Pixels Per Inch,每英寸像素数)是衡量屏幕显示精度的重要参数之一,PPI越高,屏幕显示的图像越细腻,视觉效果越好,本文将详细介绍PPI的概念、计算方法,并通过Java代码实现PPI的计算
    2025-02-02
  • 泛谈Java NIO

    泛谈Java NIO

    java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO),使用它可以提供非阻塞式的高伸缩性网络。下面我们来简单了解一下吧
    2019-05-05
  • springboot连接oracle全流程

    springboot连接oracle全流程

    这篇文章主要介绍了springboot连接oracle全流程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03

最新评论