interrupt interrupted isInterrupted 方法对比、区别与联系 多线程中篇(八)

interrupt interrupted isInterrupted 是三个“长相”很是相似的方法。
本文将对这三个方法简单的对比下,首先了解下线程中止的方式

线程中止方式

在Java中若是想中止一个线程,有三种方法
  • 采用退出标志,使得run方法执行完以后线程天然终止
  • 使用stop强行终止线程,但该方法因为安全问题已经被deprecated
  • 使用中断机制

退出标志

public class T9 extends Thread {
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running){
System.out.println("i am working ....");
}
}
public static void main(String[] args) {
T9 myThread = new T9();
myThread.setRunning(true);
myThread.start();
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
}
myThread.setRunning(false);
}
}
运行几回,结果略有不一样
image_5c64c4ae_2bf0

stop 弃用

public class T9 extends Thread {
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running) {
System.out.println("i am working ....");
}
}
public static void main(String[] args) {
T9 myThread = new T9();
myThread.setRunning(true);
myThread.start();
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
}
myThread.stop();
}
}

中断机制

stop等方法已经弃用,退出标记不够灵活有时也有问题,因此目前最合适的解决方式是借助于中断机制
中断机制是一种处理逻辑,而不是说当即中断
中断机制是一种“请求---处理”模型,是一种软中断,并不会由于中断的设置当即中止运行
中断机制的逻辑借助于“中断标志”,当请求一个线程中断时,能够经过设置目标线程的中断标志位进行操做
简单的逻辑以下图所示:
image_5c64c4ae_523
因此说,对于线程的中止的三种方式,中断机制是一种更好的方式,并且也是一种更加友好的方式。
public class T9 extends Thread { private boolean running; public void setRunning(boolean running) { this.running = running; } @Override public void run() { while (running) { System.out.println("i am working ...."); } } public static void main(String[] args) { T9 myThread = new T9(); myThread.setRunning(true); myThread.start(); myThread.interrupt(); } }
上面的代码中,尽管咱们经过myThread.interrupt();设置了标志位,可是线程仍旧继续运行,彻底并无中止的意思
image_5c64c4ae_46e8
public class T9 extends Thread {
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
while (running) {
if (Thread.currentThread().isInterrupted()) {
break;
}
System.out.println("i am working ....");
}
}
public static void main(String[] args) {
T9 myThread = new T9();
myThread.setRunning(true);
myThread.start();
try {
TimeUnit.MILLISECONDS.sleep(2);
} catch (Exception e) {
}
myThread.interrupt();
}
}
上面代码中,在run方法中判断中断标志位,若是发现中断标志被置位,那么break,也就是跳出循环
主函数中,线程启动后,主线程休眠2毫秒而后将myThread中断,程序运行一段时间后终止运行
image_5c64c4ae_3b32
因此能够看得出来,借助于中断机制对一个线程进行处理,进行中断标志置位,并不会对线程的运行产生影响,到底有何影响,重点要看到底你面对中断标志位会作什么处理。

中断标志位

经过上面的分析,咱们能够很清楚的看得出来,中断机制的核心就是借助于中断标志位
而 interrupt interrupted isInterrupted三个方法其实就是对于中断标志位的操做
从新审视下方法,两个实例方法一个静态方法
image_5c64c4ae_c76
API文档
public void interrupt()
中断一个线程(设置标志位)
除非是当前线程正在中断本身(这在任何状况下都是容许的),不然该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。
若是线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程当中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。
若是该线程在可中断的通道上的 I/O 操做中受阻,则该通道将被关闭,该线程的中断状态将被设置而且该线程将收到一个 ClosedByInterruptException。
若是该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将当即从选择操做返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法同样。
若是之前的条件都没有保存,则该线程的中断状态将被设置。
中断一个不处于活动状态的线程不须要任何做用。
抛出:
SecurityException - 若是当前线程没法修改该线程
 
注意:
若是不是线程本身在中断本身的话,会有安全管理器先进行校验,若是权限不够,将会抛出SecurityException
若是位于特殊的等待状态,好比调用wait()、wait(long)或者join()或者sleep()等方法,中断标志位将会被清除,而且收到一个InterruptedException
前面说到中断标志被置位不影响线程的正常运行,可是这个InterruptedException又是什么意思?
中断标志的确是不影响线程的运行,要看线程对于中断标志是如何进行处理的
可是若是处于等待的话,就会抛出异常
 
简单说,当一个线程正常运行的时候,能够不用搭理中断标志位;
可是若是好比在等人,在睡觉,一旦被中断就会被吵醒,吵醒了、不爽了、天然要发发牢骚,这个牢骚就是InterruptedException
public boolean isInterrupted()
测试线程是否已经中断
线程的中断状态不受该方法的影响
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
在中断发生时,若是一个线程并非alive的,中断操做将会被忽略,也会经过这个方法返回false反映出来
 
返回:
若是该线程已经中断,则返回 true;不然返回 false。
若是一个线程根本都不是alive的,调用这个方法也是返回false
image_5c64c4ae_3d75
public static boolean interrupted()
测试当前线程是否已经中断。
线程的中断状态 由该方法清除。
换句话说,若是连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态以后,且第二次调用检验完中断状态前,当前线程再次中断的状况除外)。
在中断发生时,若是一个线程并非alive的,中断操做将会被忽略,也会经过这个方法返回false反映出来
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
返回:
若是当前线程已经中断,则返回 true;不然返回 false。
接下来看一个方法
image_5c64c4ae_6e8a
测试线程是否被中断。
中断标志位将会根据参数ClearInterrupted的值决定是否会被清除
这是一个实例方法,因此须要依赖于某个实例对象
再仔细看看静态方法interrupted
image_5c64c4ae_37c4
内部借助于上面的那个私有方法
他的含义就是,测试当前线程是否被中断,而且清除中断标志位
而对于实例方法isInterrupted,仍旧是借助于本地方法,测试某个线程是否被中断,可是并不会清除线程的中断标志
image_5c64c4ae_c9c

小结

三个方法全都是用来对线程中断标志进行操做的
public void interrupt()、public boolean isInterrupted()做为实例方法是对指定线程的操做
假设中断标志位interruptState
那么对于interrupt来讲至关于set方法
  public void setInterruptState(boolean interruptState) {
    this.interruptState = interruptState;
  }
对于isInterrupted来讲,至关于get方法
  public boolean isInterruptState() {
    return interruptState;
  }
而对于interrupted() 则是至关于getter  and  setter,而且,是针对于当前线程的

总结

对于三个方法interrupt interrupted isInterrupted,重点是要了解中断标志位
从getter和setter方法的角度理解的话,可以更好地理解,从方法名中也能够很好地看得出来 
interrupt做为动词,因此是使之中断,天然是setter方法
而对于isInterrupted 典型的疑问句式,因此是对中断标志位的测试 是getter方法
interrupted看起来就奇葩了一点,因此他是set和get ,而且是针对当前线程的
这样的话就不会混淆了,毕竟名字的确是有些接近
相关文章
相关标签/搜索