三、中断一个线程

  一个拥有多个线程的Java程序要结束,需要满足两个条件之一:一是所有的非后台线程都执行结束了;二是某个线程执行了 System.exit() 方法。当你想要终结一个运行中的Java程序或者程序的用户想要取消一个线程正在执行的任务时,你都需要结束一个线程。

  Java提供中断机制来表明我们想要终止一个线程。这个机制的核心是线程必须要检查自己是否被中断,而且线程自己决定是否响应中断请求。线程可以忽略该中断请求而继续执行。

  在本秘诀中,我们将开发一个程序,这个程序创建线程,5秒后使用中断机制来结束线程。

public class Main {
    public static void main(String[] args) {
        Thread task = new PrimeGenerator();
        task.start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        task.interrupt();
    }
}

public class PrimeGenerator extends Thread {

    @Override
    public void run() {
        long number = 1L;
        while (true) {
            if (isPrime(number)) {
                System.out.printf("Number "+ number +" is Prime");
            }

            if (isInterrupted()) {
                System.out.printf("The Prime Generator has been Interrupted");
                return;
            }
            number++;
        }
    }

    private boolean isPrime(long number) {
        if (number <= 2) {
            return true;
        }
        for (long i = 2; i < number; i++) {
            if ((number % i) == 0) {
                return false;
            }
        }
        return true;
    }
}

  在 Thread 类中有一个 boolean 类型的属性来表明该类对应的线程是否被中断。通过调用 Thread 对象的 interrupt() 方法,设置其对应的线程被中断。而 isInterrupted() 方法用来返回对应线程是否被中断的状态。

  Thread 类还有一个静态方法 interrupted() 同样可以返回所在线程是否被中断的状态。但是该方法还有一个副作用:就是把线程的被中断状态重设为 false。

  线程可以忽略其被中断的状态,但这通常不是好的编程习惯。

四、控制线程的中断状态

  在上一个秘诀中,你学习了如何去中断一个线程和如何去控制线程的中断状态。如果你要中断执行的只是一个简单的线程,那么上一个秘诀就足够了。但是,如果该线程实现了一个分成多个方法的复杂算法,或者它含有实现了递归算法的方法,我们应该使用一种更好的机制去该线程的中断状态。为此,Java提供了 InterruptedException。当你在 run() 方法里发现了线程被中断时,你可以抛出并捕获该异常。

  在本秘诀中,我们的线程在目录和其子目录中来寻找含有特定名称的文件,这个程序展示如何使用 InterruptedException 来控制线程的中断。

public class FileSearch implements Runnable{
    private String initPath;
    private String 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());
            }
        }
    }

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

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

public class Main {
    public static void main(String[] args) {
        FileSearch search = new FileSearch("C:\\", "autoexec.bat");
        Thread thread = new Thread(search);
        thread.start();

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

        thread.interrupt();
    }
}

  在这个例子中,我们使用异常机制来达到终止线程运行的目的。你运行此示例程序,程序开始遍历目录并查找特定的文件。一旦线程检查到自己被中断了,它就抛出 InterruptedException 异常,继续执行 run() 方法的代码,多层的递归调用对结果没实质影响。

  Java并发API中的 sleep() 方法也有可能抛出 InterruptedException异常。

  笔者总结:本秘诀本质还是线程自己检查是否被中断,发现被中断后,通过抛出异常的方式直接跳转到了异常捕获代码处,是否多层递归对此异常跳转机制没影响。

  重要:本系列翻译文档也会在本人的微信公众号(此山是我开)第一时间发布,欢迎大家关注。

Java 7 Concurrency Cookbook 翻译 第一章 线程管理之二的更多相关文章

  1. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之一

    一.简介 在计算机的世界里,当我们谈论并发时,我们指的是一系列的任务同时运行于一个计算机中.这里说的同时运行,在计算机拥有多于一个处理器或者是一个多核处理器的时候才是真正的同时,在计算机只拥有单核处理 ...

  2. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之六

    十一.处理线程组中的未控制异常 每种编程语言一个很重要的特性就是其所提供的用来处理程序中错误情况的机制.Java语言和其他的现代语言一样,是提供了异常机制来处理对象程序中的错误.Java提供了很多的类 ...

  3. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之五

    九.使用线程本地变量 一个并发程序的最关键特征就是共享数据.这个特性在那些继承了 Thread 类或者 实现了 Runnable 接口的对象上显得更加重要. 如果你创建一个实现了 Runnable 接 ...

  4. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之四

    七.创建和运行一个后台线程 Java中有一种特别的线程叫做 deamon(后台) 线程.这类线程具有非常低的权限,并且只有在同一个程序中没有其他的正常线程在运行时才会运行.注意:当一个程序中只剩下后台 ...

  5. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之三

    五.睡眠和唤醒一个线程 有时,你会想要在一段特定的时间后再去中断线程的运行.举个例子,程序中的一个线程每一分钟检查一次传感器的状态,剩余的时间,线程应该处于空闲的状态.在这段空闲时间里,线程不会使用计 ...

  6. Java 7 Concurrency Cookbook 翻译 序言

    在日常的Java代码开发过程中,很难免地有对多线程的需求,掌握java多线程和并发的机制也是Java程序员写出更健壮和高效代码的基础.笔者找寻国内已出版的关于Java多线程和并发的的中文书籍和翻译书籍 ...

  7. java的优点和误解 《java核心技术卷i》第一章

    <java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解   1:第一章:Ja ...

  8. web前端学习python之第一章_基础语法(二)

    web前端学习python之第一章_基础语法(二) 前言:最近新做了一个管理系统,前端已经基本完成, 但是后端人手不足没人给我写接口,自力更生丰衣足食, 所以决定自学python自己给自己写接口哈哈哈 ...

  9. Android线程管理(二)——ActivityThread

    线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...

随机推荐

  1. 高可用与负载均衡(8)之聊聊 LVS重要参数和优化以及监控

    preface 在明白LVS-DR模式的部署之后,我们看看LVS的几个重要参数: 如有问题,请联系我18500777133@sina.cn [root@localhost ~]# ls /proc/s ...

  2. DS18B20函数库建立实验

    1.主代码: /* 温度传感器  */#include "DS18B20.h"#include"def.h"u16 get_temp (void){    fl ...

  3. WinForm------GridControl控件中使用SearchLookUpEdit控件的方法

    1.在数据库添加两张表,拥有主外键关系 主键表: 外键表: 2.往工具栏里拖出GridCont控件,并增加相应的列,这里对"省份"进行修改,"FileName" ...

  4. electron打包

    1.全局安装electron-packager npm install -g electron-packager 2.在项目目录下执行命令 electron-packager ./ --platfor ...

  5. BIOS设置第一启动项

    在电脑的Bois中怎样去设置第一启动项.. 对于很多新手朋友来说,BIOS满屏英文,生涩难懂,话说我原来也很排斥BIOS,界面太丑,光看界面就没什么兴趣,更谈不上深入研究,大多数人在电脑城装机的时候都 ...

  6. JavaBean简单示例

    本示例说明: 从Login.jsp中输入用户名和密码,提交,在NewFile.jsp中显示信息. ----- 类要放在一个包中!!! UserB 类文件 package model; public c ...

  7. Sort 整理

    文章.图片参考:http://www.jianshu.com/p/1b4068ccd505?hmsr=toutiao.io&utm_medium=toutiao.io&utm_sour ...

  8. JMeter 安装与使用基本教程

    JMeter使用了不同技术和协议,是一款可以进行配置和执行负载测试.性能测试和压力测试的工具. 什么是JMeter? JMeter是Apache组织的开放源代码项目,它是功能和性能测试的工具,100% ...

  9. SPL--Serializable

    Serializable[自定义序列化的接口] : 实现此接口的类将不再支持 __sleep() 和 __wakeup(). 作用: 为一些高级的序列化场景提供支持.__sleep()和__wakeu ...

  10. yum -y install与yum install有什么不同

    yum -y install 包名(支持*) :自动选择y,全自动 yum install 包名(支持*) :手动选择y or n yum remove 包名(不支持*) rpm -ivh 包名(支持 ...