初步理解

我们在看一些多线程代码的时候,有的时候会碰到使用interrupt()方法的时候。从字面的意思来理解,应该就是中断当前正在执行的线程。那么,对于一个我们设计的普通线程来说,如果我们在主线程里调用它的interrupt()方法,会不会导致它被中断呢?

比如说我们先写一段如下的代码:

  1. import java.util.concurrent.TimeUnit;
  2. public class ThreadCon extends Thread
  3. {
  4. public void run()
  5. {
  6. for(int i = 0; i < Integer.MAX_VALUE; i++)
  7. {
  8. System.out.println(i);
  9. }
  10. }
  11. public static void main(String[] args)
  12. {
  13. ThreadCon thread = new ThreadCon();
  14. thread.start();
  15. System.out.println("main thread");
  16. try
  17. {
  18. TimeUnit.SECONDS.sleep(2);
  19. }
  20. catch(InterruptedException e)
  21. {
  22. e.printStackTrace();
  23. }
  24. thread.interrupt();
  25. }
  26. }

这是一段比较简单的示例,我们在开始的时候启动一个子线程,这个线程打印从0到Integer.MAX_VALUE 的值。而主线程先sleep 2秒钟。然后再尝试去中断子线程。

如果我们去运行前面这一段代码,会发现子线程会一直在输出数字结果,它根本就不会停下来。部分结果的输出如下:

  1. 141318
  2. 141319
  3. 141320
  4. 141321
  5. 141322
  6. 141323
  7. 141324
  8. 141325

由此可见,我们对一个子线程发interrupt的消息时,如果线程是在运行的状态之下,它会忽略这个请求而继续执行的。

那么,在什么情况下才会导致这个触发的interrupt消息让子线程能够响应呢?

interrupt方法处理方式

interrupt方法调用的时候会设置该线程的interrupt标识位(flag),相当于设置了一个状态信息。执行的子线程需要检查该标识位是否被设置了然后才能做后续的执行步骤。这个检查的方法就是isInterrupted()。这样,在一旦检测到这个位被设置之后,我们就可以采取对应的措施。

我们在前面的代码的基础上做一点修改:

  1. import java.util.concurrent.TimeUnit;
  2. public class ThreadCon extends Thread
  3. {
  4. public void run()
  5. {
  6. for(int i = 0; i < Integer.MAX_VALUE; i++)
  7. {
  8. System.out.println(i);
  9. if(isInterrupted())
  10. {
  11. System.out.println("Interrupted...");
  12. return;
  13. }
  14. }
  15. }
  16. public static void main(String[] args)
  17. {
  18. ThreadCon thread = new ThreadCon();
  19. thread.start();
  20. System.out.println("main thread");
  21. try
  22. {
  23. TimeUnit.SECONDS.sleep(2);
  24. }
  25. catch(InterruptedException e)
  26. {
  27. e.printStackTrace();
  28. }
  29. thread.interrupt();
  30. }
  31. }

这里,我们在run方法的循环里增加了一个判断,调用isInterrupted方法。如果被设置为interrupted,则显示一个信息然后退出。这个时候如果我们再执行这部分代码,会发现结果如下:

  1. 141370
  2. 141371
  3. 141372
  4. 141373
  5. 141374
  6. 141375
  7. 141376
  8. 141377
  9. 141378
  10. Interrupted...

所以说,从前面的代码中可以看到,这是一种处理interrupt方法的手段。在实际的一些应用中,我们可以通过抛出异常然后由调用程序捕捉的方式来处理。比如在前面的这个示例里,我们判断了isInterrupted了之后就在接着的部分处理了。如果我们希望由调用该方法的使用者来处理。可以在这里不做进一步的处理而是直接写一个throw new InterruptedException()。

这里也有一个稍微复杂点的示例,通过遍历文件系统,然后在处理的子方法里面来抛出异常,再由调用的方法来处理。

  1. import java.io.File;
  2. public class FileSearch implements Runnable {
  3. private String initPath;
  4. private String fileName;
  5. public FileSearch(String initPath, String fileName) {
  6. this.initPath = initPath;
  7. this.fileName = fileName;
  8. }
  9. @Override
  10. public void run() {
  11. File file = new File(initPath);
  12. if(file.isDirectory()) {
  13. try {
  14. directoryProcess(file);
  15. } catch(InterruptedException e) {
  16. System.out.printf("%s: The search has been interrupted",
  17. Thread.currentThread().getName());
  18. }
  19. }
  20. }
  21. private void directoryProcess(File file) throws InterruptedException {
  22. File[] list = file.listFiles();
  23. if(list != null) {
  24. for(int i = 0; i < list.length; i++) {
  25. if(list[i].isDirectory()) {
  26. directoryProcess(list[i]);
  27. } else {
  28. fileProcess(list[i]);
  29. }
  30. }
  31. }
  32. if(Thread.interrupted()) {
  33. throw new InterruptedException();
  34. }
  35. }
  36. private void fileProcess(File file) throws InterruptedException {
  37. if(file.getName().equals(fileName)) {
  38. System.out.printf("%s : %s\n", Thread.currentThread().getName(),
  39. file.getAbsolutePath());
  40. }
  41. if(Thread.interrupted()) {
  42. throw new InterruptedException();
  43. }
  44. }
  45. }

启用该线程的部分代码如下:

  1. import java.util.concurrent.TimeUnit;
  2. /**
  3. *  Main class of the example. Search for the autoexect.bat file
  4. *  on the Windows root folder and its subfolders during ten seconds
  5. *  and then, interrupts the Thread
  6. */
  7. public class Main {
  8. /**
  9. * Main method of the core. Search for the autoexect.bat file
  10. * on the Windows root folder and its subfolders during ten seconds
  11. * and then, interrupts the Thread
  12. * @param args
  13. */
  14. public static void main(String[] args) {
  15. // Creates the Runnable object and the Thread to run it
  16. FileSearch searcher=new FileSearch("C:\\","autoexec.bat");
  17. Thread thread=new Thread(searcher);
  18. // Starts the Thread
  19. thread.start();
  20. // Wait for ten seconds
  21. try {
  22. TimeUnit.SECONDS.sleep(10);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. // Interrupts the thread
  27. thread.interrupt();
  28. }
  29. }

总结

interrupt方法的效果是它会设置线程的状态位,但是对于正在运行状态的线程并不会导致它被立即中断。只有执行的线程在检测到相关信息后采取对应措施。我们常用的措施一般是调用isInterrupted方法或者捕捉被调用方法抛出的InterruptedException来做处理。整体的应用并不复杂。

Thread interrupt方法解析的更多相关文章

  1. 注意Thread.interrupt()方法的真正作用并不是用来中断线程

      程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误.      在本篇文章中,我们针对这些难题之一:如何中断一个正在 ...

  2. 调用Thread.interrupt()方法到底会发生什么?

    1. 当线程处于Blocked状态(sleep,wait,join),线程会退出阻塞状态,并抛出一个InterruptedException.park除外,它有响应但是不会抛出异常 2. 当线程处于R ...

  3. Thread.interrupt()方法理解

    原博客地址: 多线程编程 实战篇 (四) 不客气地说,至少有一半人认为,线程的"中断"就是让线程停止. 如果你也这么认为,那你对多线程编程还没有入门. 在java中,线程的中断(i ...

  4. Java Thread.interrupt 害人! 中断JAVA线程(zz)

    http://www.blogjava.net/jinfeng_wang/archive/2012/04/22/196477.html#376322 ————————————————————————— ...

  5. 停止Java线程,小心interrupt()方法

    来源:http://blog.csdn.net/wxwzy738/article/details/8516253 程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决 ...

  6. Java线程停止interrupt()方法

    程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误.在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程. 中 ...

  7. 多线程 interrupt()方法

    java interrupt()方法只是设置线程的中断标记,当对处于阻塞状态的线程调用interrupt方法时(处于阻塞状态的线程是调用sleep, wait, join 的线程),会抛出Interr ...

  8. Thread interrupt() 线程中断的详细说明

    GitHub源码地址 原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止 ...

  9. 线程的Interrupt方法与InterruptedException解析

    线程阻塞状态与等待状态(当一个线程处于被阻塞或等待状态时,它暂时不活动,不允许任何代码且消耗最少的资源) 当一个线程试图获得一个内部的对象锁(而不是java.util.concurrent库中的锁), ...

随机推荐

  1. page cache和buffer cache

    因为要优化I/O性能,所以要理解一下这两个概念,这两个cache着实让我迷糊了好久,通过查资料大概明白了两者的区别,试着说下. page cache:文件系统层级的缓存,从磁盘里读取的内容是存储到这里 ...

  2. 了解常见的浏览器内核 Trident,Geckos,Presto,Webkit

    了解常见的浏览器内核 Trident,Geckos,Presto,Webkit 内核只是一个通俗的说法,英文名称为"Layout engine",翻译过来就是"排版引擎& ...

  3. QR Code於台灣各行業的行銷應用案例介紹

    當走在東京的大街小巷時,在五花八門的廣告看板.雜誌.護照簽證.海關.宣傳品.廣告.旅遊和導覽手冊.產品包裝.甚至在餐廳菜單上,皆可看到上面有一組黑色神秘二維條碼圖案:QR Code,當看到有興趣的商品 ...

  4. 算法导论练习6.5-8 k路合并

    题目: 请给出一个时间为O(nlgk).用来将k个已排序链表合并为一个排序链表的算法.此处n为所有输入链表中元素的总数.(提示:用一个最小堆来做k路合并. 看到题目第个想到的是归并排序过程中的归并操作 ...

  5. 取得phpcms网站下所有栏目的内容链接

    今天做了一个小功能,就是取得公司网站的所有文章的内容地址,公司网站是用phpcms 做的,感觉还蛮简单的,记录下: <?php $conf['DB_USER'] = 'user'; $conf[ ...

  6. Codeforces 235B Let&#39;s Play Osu! 概率dp(水

    题目链接:点击打开链接 给定n表示有n个格子 以下每一个格子为O的概率是多少. 对于一段连续 x 个O的价值就是 x*x ; 问: 获得的价值的期望是多少. 思路: 把公式拆一下.. #include ...

  7. 史上最简单的Hibernate入门简单介绍

    事实上Hibernate本身是个独立的框架,它不须要不论什么web server或application server的支持.然而,大多数的Hibernate入门介绍都加入了非常多非Hibernate ...

  8. SQL Server 2008 错误 233 的解决办法

    问题一.忘记了登录Microsoft SQL Server 2008 的sa的登录密码 解决方法:先用windows身份验证的方式登录进去,然后在‘安全性’-‘登录’-右键单击‘sa’-‘属性’,修改 ...

  9. iOS 相互引用引起内存泄露问题说明

    release动作只会对自身计数减一,而不会对属性发出release消息,只有该对象的引用计数为0,系统才会对该对象的所有属性发出release消息 类A的属性有类B,类B的属性有类A,而且两者都是强 ...

  10. Objective-c 集合对象

    集合(NSSet)是一组单值对象的组合,集合对象的操作包括:搜索,添加,删除集合中的成员(可变集合的功能),比较两个集合,计算两个集合的交集,并集等. 下面来看下(NSSet)的方法: 1)集合的构建 ...