前言
想到让线程停止的方法,可能第一个冒出来的是stop()方法,但是这个方法已经停止使用,是一个废弃的方法,因为由它会造成很多的问题,比如数据的不一致等问题。现在一般会使用另外的方法对线程进行停止,本篇主要对Thread类中interrupt()、interrupted()和isInterrupted()方法进行详解。
一、方法简介
1. interrupt()方法
其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。
2. interrupted()方法
作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。并且它为静态方法,实际上调用的还是isInterrupted()方法。
1 | public static boolean interrupted() { |
3. isInterrupted()方法
作用是只测试此线程是否被中断 ,不清除中断状态。它为非静态方法。
1 | public boolean isInterrupted() { |
二、例子说明
例一
1 | public class Main { |
输出结果:
第一次调用 true
第二次调用 false
Thread.currentThread().interrupt();执行之后,当前线程的中断标志为true,代表有中断,这里的当前线程也就是main线程。第一次调用Thread.interrupted()后,返回true,也就是main线程中断标志为true,并且清除中断标志位,使之为false,也就是没有中断的意思。所以在第二次调用Thread.interrupted()后输出false,原来的中断标志位被清除了。
例二
在例一的基础上进行修改,因为interrupted()会清除中断标志位,如果这边采用isInterrupted()会达到怎样的效果。
1 | public class Main { |
输出结果:
第一次调用 true
第二次调用 true
Thread.currentThread().interrupt();也就是把当前的线程中断,也就是main线程,中断标志为true,所以在第一次调用的时候会输出true,但是isInterrupted()方法是不清除中断标志位的,所以第二次调用的时候也是true。
例三
1 | public class Main { |
输出结果:
第一次调用 false
第二次调用 false
mmThread.interrupt();表示mmThread的中断标志位为true,但是在后面调用的Thread.interrupted()指的是main线程的中断标志位状态,因为程序中没有对main的中断标志进行过标记,所以没有中断的时候,故最后输出的都是false。
例四
1 | public class Main { |
输出结果:
第一次调用 true
第二次调用 true
第一次调用后,输出的还是true,意味着中断标志位被标记。因为调用的是isInterrupted()函数,所以不会清除中断位。
例五(易混淆)
1 | public class Main { |
输出结果:
第一次调用 false
第二次调用 false
在之前的mmThread.interrupt();中明明就标记了中断标记位,但是输出的确实false,那么为何会这样?注意:myThread.Interrupted()指的是当前线程是否被中断,注意这个当前线程!!也就是当前线程其实是main线程,那么mmThread被中断也就和它没有任何关系了。也就是,myThread.interrupted()等价于Thread.interrupted()。
例六
若要通过调用interrupt()来终止某个线程,其实只要在线程的run()中进行处理即可。比如跳出run()方法让线程结束。
1 | public class myThread extends Thread { |
1 | public class Main { |
运行结果:
i=0
i=…(中间忽略了。。。)
i=61
检测到中断,跳出线程
不是直接跳出中断,而是要运行完再跳出!!!
这边可以看到,在run()方法中进行判断,当中断为true的时候,线程被中断,但是还有一个需要注意的地方,即使检测到了中断,但是并不是立即结束线程,而是执行完run()才结束的线程。
例七
这边顺便说一下启动线程的start()和run()的区别,先上代码,将main函数中的start()方法改为run()方法。
1 | public class Main { |
运行结果:
i=1
i=…(中间忽略了。。。)
i=9999
不是直接跳出中断,而是要运行完再跳出!!!
可以看到,当线程内容执行完才会执行main线程中剩下的内容。总结一下,run()方法是同步方法,线程mmThread启动后,要等这个线程执行完,才会继续执行main线程中下一句代码。而start()方法是异步方法,也就是在执行mmThread线程的同时,也会继续执行main这个线程,所以才会导致执行到一半,就执行了interrupt()函数,终止了线程。
最后总结,关于这三个方法,interrupt()是给线程设置中断标志,interrupted()是检测中断并清除中断状态,isInterrupted()只检测中断。还有重要的一点就是interrupted()作用于当前线程(注意理解这个当前线程的意思,结合例五),interrupt()和isInterrupted()作用于此线程,即代码中调用此方法的实例所代表的线程。