一 interrupt :
如下方法会使得当前线程进入阻塞状态:而调用当前线程的interrupt方法会打断阻塞:
object的wait 方法
thread的sleep 方法
thread的join方法
interruptiblechannel的io操作
selector的wakeup方法
其他方法
上述若干方法都会是线程进入阻塞状态,若另外一个线程调用阻塞线程的interrupt方法,则会打断这个阻塞,因此可以称为可中断方法,打断一个线程并不等于该线程的生命周期结束,仅仅是打断了当前线程的阻塞状态,
一旦线程在阻塞的情况下被打断都会抛出一个interruptedExcption 的异常,这个异常就像一个signal信号),一样通知当前线程被打断了,如下:
public class ThreadPriority {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(() ->{
try {
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("i am be interrupted");
}
});
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
thread.interrupt();
}
}
上面的代码创建一个线程,并且企图偷懒一分钟。不过可惜大约在几毫秒之后被主线程调用interrupt方法打断,程序执行结果就是 i am be interrupted、
interrupt方法做了什么呢?在一个线程内部存在名为interrupt flag 的标识,如果一个线程被interrupt ,那么他的flag将被设置,但是如果当前线程正在执行可中断方法被阻塞时,调用interrupt方法将其中断,反而会导致flag被清除,,如果一个线程已经是死亡状态,那么尝试对其的interrupt 会直接被忽略
isinterrupted
isinterrupted 是thread类的一个成员方法,它主要判断当前线程是否被中断,该方法仅仅是对interrupt标识的一个判断,并不会影响标识发生任何改变,看一个例子:
public class ThreadPriority {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread() {
@Override
public void run() {
while(true) {
}
}
};
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
System.out.printf("there is interrupted?%s\n",thread.isInterrupted());
thread.interrupt();
System.out.printf("there is interrupted?%s\n",thread.isInterrupted());
}
}
结果:
there is interrupted?false
there is interrupted?true
上面代码中定义了一个线程,并且在线程执行单员中写了一个空的死循环,为什么不写sleep呢? 因为sleep 是一个可中断方法,会捕获到中断信号,从而干扰到我们程序的结果,,可中断方法捕获到中断信号(signal)之后也就是捕获了interruptException 异常之后会擦除掉interrupt 的标识,对上面的程序稍作修改,如下:
public class ThreadPriority {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread() {
@Override
public void run() {
try {
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
System.out.printf("i am be interrupt ? %s\n",isInterrupted() );
}
}
};
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
System.out.printf("there is interrupted?%s\n",thread.isInterrupted());
thread.interrupt();
TimeUnit.MILLISECONDS.sleep(2);
System.out.printf("there is interrupted?%s\n",thread.isInterrupted());
}
}
结果:、
there is interrupted?false
i am be interrupt ? false
there is interrupted?false
由于在run 方法中使用了sleep这个可中断方法,他会捕获到中断信号,并且会擦除interrupt 标识,因此执行结果会是flase,
当中断方法捕获到了中断信号之后,为了不影响线程中其他方法的执行,将线程的interrupt标识复位,
interrupted
interrupted 是一个静态方法,虽然其也用于判断当前线程是否被中断,但是和isinterrupted是有很大区别的,调用该方法会直接擦除interrupt 标识,需要注意的是 ,如果当前线程被打断了,那么第一次调用interrupted返回true,并且立即擦除interrupt标识,第二次包括以后都会返回false,除非在此期间,线程又一次被打断,例如:
public class ThreadPriority {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread() {
@Override
public void run() {
while(true) {
System.out.println(Thread.interrupted());
}
}
};
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
// System.out.printf("there is interrupted?%s\n",thread.isInterrupted());
thread.interrupt();
// TimeUnit.MILLISECONDS.sleep(2);
// System.out.printf("there is interrupted?%s\n",thread.isInterrupted());
}
}
同样由于不想受到可中断方法如sleep的影响,在run方法中没有进行休眠,
结果:
很多false中有一个true,也就是interrupted方法判断到了他被中断,立即擦除了中断标识,后面都是false