Thread interrupt方法解析
初步理解
我们在看一些多线程代码的时候,有的时候会碰到使用interrupt()方法的时候。从字面的意思来理解,应该就是中断当前正在执行的线程。那么,对于一个我们设计的普通线程来说,如果我们在主线程里调用它的interrupt()方法,会不会导致它被中断呢?
比如说我们先写一段如下的代码:
- import java.util.concurrent.TimeUnit;
- public class ThreadCon extends Thread
- {
- public void run()
- {
- for(int i = 0; i < Integer.MAX_VALUE; i++)
- {
- System.out.println(i);
- }
- }
- public static void main(String[] args)
- {
- ThreadCon thread = new ThreadCon();
- thread.start();
- System.out.println("main thread");
- try
- {
- TimeUnit.SECONDS.sleep(2);
- }
- catch(InterruptedException e)
- {
- e.printStackTrace();
- }
- thread.interrupt();
- }
- }
这是一段比较简单的示例,我们在开始的时候启动一个子线程,这个线程打印从0到Integer.MAX_VALUE 的值。而主线程先sleep 2秒钟。然后再尝试去中断子线程。
如果我们去运行前面这一段代码,会发现子线程会一直在输出数字结果,它根本就不会停下来。部分结果的输出如下:
- 141318
- 141319
- 141320
- 141321
- 141322
- 141323
- 141324
- 141325
由此可见,我们对一个子线程发interrupt的消息时,如果线程是在运行的状态之下,它会忽略这个请求而继续执行的。
那么,在什么情况下才会导致这个触发的interrupt消息让子线程能够响应呢?
interrupt方法处理方式
interrupt方法调用的时候会设置该线程的interrupt标识位(flag),相当于设置了一个状态信息。执行的子线程需要检查该标识位是否被设置了然后才能做后续的执行步骤。这个检查的方法就是isInterrupted()。这样,在一旦检测到这个位被设置之后,我们就可以采取对应的措施。
我们在前面的代码的基础上做一点修改:
- import java.util.concurrent.TimeUnit;
- public class ThreadCon extends Thread
- {
- public void run()
- {
- for(int i = 0; i < Integer.MAX_VALUE; i++)
- {
- System.out.println(i);
- if(isInterrupted())
- {
- System.out.println("Interrupted...");
- return;
- }
- }
- }
- public static void main(String[] args)
- {
- ThreadCon thread = new ThreadCon();
- thread.start();
- System.out.println("main thread");
- try
- {
- TimeUnit.SECONDS.sleep(2);
- }
- catch(InterruptedException e)
- {
- e.printStackTrace();
- }
- thread.interrupt();
- }
- }
这里,我们在run方法的循环里增加了一个判断,调用isInterrupted方法。如果被设置为interrupted,则显示一个信息然后退出。这个时候如果我们再执行这部分代码,会发现结果如下:
- 141370
- 141371
- 141372
- 141373
- 141374
- 141375
- 141376
- 141377
- 141378
- Interrupted...
所以说,从前面的代码中可以看到,这是一种处理interrupt方法的手段。在实际的一些应用中,我们可以通过抛出异常然后由调用程序捕捉的方式来处理。比如在前面的这个示例里,我们判断了isInterrupted了之后就在接着的部分处理了。如果我们希望由调用该方法的使用者来处理。可以在这里不做进一步的处理而是直接写一个throw new InterruptedException()。
这里也有一个稍微复杂点的示例,通过遍历文件系统,然后在处理的子方法里面来抛出异常,再由调用的方法来处理。
- import java.io.File;
- 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();
- }
- }
- }
启用该线程的部分代码如下:
- import java.util.concurrent.TimeUnit;
- /**
- * Main class of the example. Search for the autoexect.bat file
- * on the Windows root folder and its subfolders during ten seconds
- * and then, interrupts the Thread
- */
- public class Main {
- /**
- * Main method of the core. Search for the autoexect.bat file
- * on the Windows root folder and its subfolders during ten seconds
- * and then, interrupts the Thread
- * @param args
- */
- public static void main(String[] args) {
- // Creates the Runnable object and the Thread to run it
- FileSearch searcher=new FileSearch("C:\\","autoexec.bat");
- Thread thread=new Thread(searcher);
- // Starts the Thread
- thread.start();
- // Wait for ten seconds
- try {
- TimeUnit.SECONDS.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // Interrupts the thread
- thread.interrupt();
- }
- }
总结
interrupt方法的效果是它会设置线程的状态位,但是对于正在运行状态的线程并不会导致它被立即中断。只有执行的线程在检测到相关信息后采取对应措施。我们常用的措施一般是调用isInterrupted方法或者捕捉被调用方法抛出的InterruptedException来做处理。整体的应用并不复杂。
Thread interrupt方法解析的更多相关文章
- 注意Thread.interrupt()方法的真正作用并不是用来中断线程
程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误. 在本篇文章中,我们针对这些难题之一:如何中断一个正在 ...
- 调用Thread.interrupt()方法到底会发生什么?
1. 当线程处于Blocked状态(sleep,wait,join),线程会退出阻塞状态,并抛出一个InterruptedException.park除外,它有响应但是不会抛出异常 2. 当线程处于R ...
- Thread.interrupt()方法理解
原博客地址: 多线程编程 实战篇 (四) 不客气地说,至少有一半人认为,线程的"中断"就是让线程停止. 如果你也这么认为,那你对多线程编程还没有入门. 在java中,线程的中断(i ...
- Java Thread.interrupt 害人! 中断JAVA线程(zz)
http://www.blogjava.net/jinfeng_wang/archive/2012/04/22/196477.html#376322 ————————————————————————— ...
- 停止Java线程,小心interrupt()方法
来源:http://blog.csdn.net/wxwzy738/article/details/8516253 程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决 ...
- Java线程停止interrupt()方法
程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误.在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程. 中 ...
- 多线程 interrupt()方法
java interrupt()方法只是设置线程的中断标记,当对处于阻塞状态的线程调用interrupt方法时(处于阻塞状态的线程是调用sleep, wait, join 的线程),会抛出Interr ...
- Thread interrupt() 线程中断的详细说明
GitHub源码地址 原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止 ...
- 线程的Interrupt方法与InterruptedException解析
线程阻塞状态与等待状态(当一个线程处于被阻塞或等待状态时,它暂时不活动,不允许任何代码且消耗最少的资源) 当一个线程试图获得一个内部的对象锁(而不是java.util.concurrent库中的锁), ...
随机推荐
- 自己模拟实现math.h中的函数
之前一直都很迷惑pow()函数时怎么实现的,对于整数次的幂我还能很容易做到,但是对于分数次幂就不是那么好做了.需要一些高等数学级数的知识. 我这里实现了求ln(x), pow(double x, do ...
- 01-复杂度2. Maximum Subsequence Sum (25)
Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, ...
- HDU 1002 A + B Problem II(大整数相加)
A + B Problem II Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u De ...
- CreateFileMapping使用方法
CreateFileMapping的MSDN翻译和使用心得 測试创建和打开文件映射的时候老是得到"句柄无效"的错误, 细致看了MSDN以后才发觉是函数认识不透, 这里把相关的解 ...
- linux搭建邮件服务器
一.概述: 在配置邮件服务器之前,先解释几个概念. 通常使用Email都很容易,但是Internet的邮件系统是通过几个复杂的部分连接而成的,对于最终用户而言,我们熟悉的Outlook,Foxmail ...
- JS年月日三级联动下拉框日期选择代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Ajax+asp.net实现用户登陆 转自http://www.shangxueba.com/jingyan/2933319.html
这篇文章主要介绍了Ajax+asp.net实现用户登陆,主要是为了练习ajax的使用方法,有需要的小伙伴参考下. 以用户登录为例练习ajax的使用方法 login.html <!DOCTYPE ...
- Vijos 1083 小白逛公园(线段树)
线段树,每个结点维护区间内的最大值M,和sum,最大前缀和lm,最大后缀和rm. 若要求区间为[a,b],则答案max(此区间M,左儿子M,右儿子M,左儿子rm+右儿子lm). ----------- ...
- 简单十步让你全面理解SQL
很多程序员认为SQL是一头难以驯服的野兽.它是为数不多的声明性语言之一,也因为这样,其展示了完全不同于其他的表现形式.命令式语言. 面向对象语言甚至函数式编程语言(虽然有些人觉得SQL 还是有些类似功 ...
- JQuery中回车键登陆
//点击回车键 //王东升/2015/3/11 document.onkeydown = function (event) { var e = event ? event : (window.even ...