Java 7 Concurrency Cookbook 翻译 第一章 线程管理之二
三、中断一个线程
一个拥有多个线程的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 翻译 第一章 线程管理之二的更多相关文章
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之一
一.简介 在计算机的世界里,当我们谈论并发时,我们指的是一系列的任务同时运行于一个计算机中.这里说的同时运行,在计算机拥有多于一个处理器或者是一个多核处理器的时候才是真正的同时,在计算机只拥有单核处理 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之六
十一.处理线程组中的未控制异常 每种编程语言一个很重要的特性就是其所提供的用来处理程序中错误情况的机制.Java语言和其他的现代语言一样,是提供了异常机制来处理对象程序中的错误.Java提供了很多的类 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之五
九.使用线程本地变量 一个并发程序的最关键特征就是共享数据.这个特性在那些继承了 Thread 类或者 实现了 Runnable 接口的对象上显得更加重要. 如果你创建一个实现了 Runnable 接 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之四
七.创建和运行一个后台线程 Java中有一种特别的线程叫做 deamon(后台) 线程.这类线程具有非常低的权限,并且只有在同一个程序中没有其他的正常线程在运行时才会运行.注意:当一个程序中只剩下后台 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之三
五.睡眠和唤醒一个线程 有时,你会想要在一段特定的时间后再去中断线程的运行.举个例子,程序中的一个线程每一分钟检查一次传感器的状态,剩余的时间,线程应该处于空闲的状态.在这段空闲时间里,线程不会使用计 ...
- Java 7 Concurrency Cookbook 翻译 序言
在日常的Java代码开发过程中,很难免地有对多线程的需求,掌握java多线程和并发的机制也是Java程序员写出更健壮和高效代码的基础.笔者找寻国内已出版的关于Java多线程和并发的的中文书籍和翻译书籍 ...
- java的优点和误解 《java核心技术卷i》第一章
<java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解 1:第一章:Ja ...
- web前端学习python之第一章_基础语法(二)
web前端学习python之第一章_基础语法(二) 前言:最近新做了一个管理系统,前端已经基本完成, 但是后端人手不足没人给我写接口,自力更生丰衣足食, 所以决定自学python自己给自己写接口哈哈哈 ...
- Android线程管理(二)——ActivityThread
线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...
随机推荐
- SOA 和webservice 的区别
http://blog.csdn.net/bingjing12345/article/details/7575566 Web service 的具体过程 需要明确的东西 1, 服务器端 和 客户端 之 ...
- 【原】React中,map出来的元素添加事件无法使用
在使用react中,经常用到react的map函数,用法和jquery里中的map一样,但是,如果你在每个map出来的元素中添加,你会发觉添加的事件无法关联, 比如,我们很多的评论,我需要在每个评论下 ...
- Dijkstra最短路径算法实例
#include <stdio.h>#include <stdlib.h>/* Dijkstra算法 */#define VNUM 5#define MV 65536int P ...
- 转移大于2m的pdf文件到另外一个文件夹
转移大于2m的pdf文件到另外一个文件夹 remove_moret2M_pdfs.py # -*- coding: utf-8 -*- """ Created on Mo ...
- ArcGIS Server开发教程系列(8)ArcGIS API for Javascript-控件(小部件)(续)纯代码
完整代码如下: <html> <head> <meta http-equiv="Content-Type" content="text/ht ...
- BigInteger类
当一个数字非常大时,则肯定无法使用基本类型接受,所以使用了BigInteger类. BigInteger类表示是大整数类,定义在java.math包中,如果在操作时一个整型数据已经超过了整数的最大类型 ...
- 安装weinre在PC端调试移动端
1.使用node安装weinre. 2.启动weinre, weinre --httpPort 8081 --boundHost -all- 3.在浏览器打开 http://localhost:80 ...
- sql FOR XML PATH
FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作.那么以一个实例为主 ...
- C#中事件的使用
C#中事件的使用 http://www.cnblogs.com/wayfarer/archive/2004/04/20/6712.html 用一个例子来说明事件的使用. 创建一个简单的类,名为Fil ...
- Yii2的深入学习--自动加载机制(转)
Yii2 的自动加载分两部分,一部分是 Composer 的自动加载机制,另一部分是 Yii2 框架自身的自动加载机制. Composer自动加载 对于库的自动加载信息,Composer 生成了一个 ...