三、中断一个线程

  一个拥有多个线程的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. 机器学习笔记--KNN算法1

    前言 Hello ,everyone. 我是小花.大四毕业,留在学校有点事情,就在这里和大家吹吹我们的狐朋狗友算法---KNN算法,为什么叫狐朋狗友算法呢,在这里我先卖个关子,且听我慢慢道来. 一 K ...

  2. JS-节点属性(常用!)

    (开始很生疏,不想看的知识点,后来DOM中用的特别多,才发现很重要.还有几个点,是比较容易忽略的,值得注意!) <!DOCTYPE html><html> <head&g ...

  3. wpf 拖图片到窗体

    前台代码:<Window x:Class="拖拽.MainWindow"        xmlns="http://schemas.microsoft.com/wi ...

  4. autofac 注入普通服务和WCF服务

    using Autofac;using Autofac.Builder;using Autofac.Core; //实现Autofac扩展 public static AutofacRegisterW ...

  5. TCP/UDP端口列表

    http://zh.wikipedia.org/wiki/TCP/UDP%E7%AB%AF%E5%8F%A3%E5%88%97%E8%A1%A8 TCP/UDP端口列表     本条目可通过翻译外语维 ...

  6. 9月12日JavaScript脚本语言

    JS脚本语言 JS脚本语言全称JavaScript,是网页里面使用的脚本语言,也是一门非常强大的语言. 一.基础语法 1.注释语法 单行注释:// 多行注释:/**/ 2.输出语法 ①alert(信息 ...

  7. Java同步synchronized与死锁

    多个线程要操作同一资源时就有可能出现资源的同步问题. 同步就是指多个操作在同一个时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续执行. 解决资源共享的同步操作,可以使用同步代码块和同 ...

  8. OpenGL Driver Architecture[转]

    http://www.cnblogs.com/cgwolver/archive/2009/01/04/1368350.html

  9. Visual Studio低版本升级到Visual Studio 2012出现Warning LNK4075

    Warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification

  10. 创建自己的Activity

    创建自己的Activity 1.新建class,继承Activity类 2.重写新建类的onCreate 方法 public class SecondActivity extends Activity ...