线程中断
2021-06-24 06:04
标签:表示 中断处理 断线 out err join() 没有 程序设计 mil 在Java中,线程中断是一种重要的线程协作机制,从表面上来看,中断就是让目标线程停止执行的意思,实际上却并非如此。 严格上讲,线程中断并不会使线程立即退出,而是给线程发送一个通知,告知目标线程,有人希望你退出了。至于目标线程接到通知后如何处理,则完全由目标线程自行决定。这点很重要,如果中断后,线程立即无条件退出,这种方式太暴力了,可能会引起一些数据不一致的问题,线程的stop()方法就是因为这个原因被弃用。 与线程中断有关的方法有三个: 1.interrupt(): 先看源码: 从注释就可以明显看出,interrupt()方法的作用就是“Just to set the interrupt flag”,即仅仅设置中断标识位。 2.isInterrupted(): 先看源码: 这个方法通过检查中断标志位,判断当前线程是否被中断。 3.interrupted(): 先看源码: 这是一个静态方法,也是用来判断当前线程的中断状态,但同时会清除当前线程的中断标志位状态。也就是说,连续调用该方法两次,那么第二次的返回值一定是false。 下面举例说明这三个方法: 上面这个例子,虽然对t1进行了中断,但是运行后发现,线程t1并没有中断,由此可见,即使线程被设置上了中断状态,但是这个中断不会发生任何作用。 如果希望t1在中断后退出,就必须为它增加相应的中断处理代码,将上述例子修改为: 输出结果: 表示线程中断成功。上述例子增加的部分 Thread.currentThread().isInterrupted() 判断当前线程是否被中断了,如果是,就退出循环体,结束线程。 思考: 存在这样的情况,当线程被阻塞的时候,比如被Object.wait()、Thread.join()或者Thread.sleep()这三种之一的方法阻塞时,该怎么中断线程呢? 有一种情况就是,线程在阻塞前恰好给自己设置了中断标识位,即调用了interrupt()方法,但是线程都阻塞了,当然也就不能通过 isInterrupt()方法来自己中断了;如果中断表示位都没有,就更不可能自己中断了。那么应该怎么办呢? 方法当然是有的,下面以sleep()方法为例,先来看看sleep()方法: Thread.sleep()方法会让目标线程休眠若干时间,它会抛出一个 InterruptedException 中断异常。这个异常不是运行时异常,也就是说程序必须捕获并且处理它,当线程在sleep()时,如果被中断,这个异常就产生了。 看下面的例子: 输出结果: 从输出结果来看,线程t1 start后,是没有中断标识位的,t1线程sleep 2秒,主线程main sleep了 1 秒,当t1还在sleep的时候,main线程执行了 t1.sleep(),所以t1是在sleep的时候被中断,由此捕获到异常,并设置了中断标识位,最后由break 退出中断线程。 注意: Thread.sleep()方法由于中断而抛出异常,此时,它会清除中断标记,由上面输出结果可以看出在打印出中断后,中断标记位为false,如果不加上中断标识位,线程就不会中断,因此在异常处理中,再次设置上中断标识位。 参考: 《Java高并发程序设计》 葛一鸣 郭超 著 线程中断 标签:表示 中断处理 断线 out err join() 没有 程序设计 mil 原文地址:https://www.cnblogs.com/Joe-Go/p/9670271.htmlpublic void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
public boolean isInterrupted() {
return isInterrupted(false);
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
@Override
public void run(){
while(true){
Thread.yield();
}
}
};
t1.start();
Thread.sleep(1000);
t1.interrupt();
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
@Override
public void run(){
while(true){
if (Thread.currentThread().isInterrupted()) {
System.out.println("t1 Interrupted!");
break;
}
Thread.yield();
}
}
};
t1.start();
Thread.sleep(1000);
t1.interrupt();
}
t1 Interrupted!
public static native void sleep(long millis) throws InterruptedException;
public static void main(String[] args) throws InterruptedException {
//将线程取名为t1
Thread t1 = new Thread("t1"){
@Override
public void run(){
while(true){
if (Thread.currentThread().isInterrupted()) {
System.out.println("t1 Interrupted!");
break;
}
try {
System.out.println(Thread.currentThread().getName());//打印出当前线程的名字
System.out.println(Thread.currentThread().isInterrupted());//查看当前线程的中断标识位
System.out.println("开始睡觉");
Thread.sleep(2000);
System.out.println("睡觉结束");
} catch (InterruptedException e) {
System.out.println("Interrupted When Sleep!");
System.out.println(Thread.currentThread().isInterrupted());//查看当前线程的中断标识位
//设置中断状态
Thread.currentThread().interrupt();
}
System.out.println("让出资源");
Thread.yield();
}
}
};
t1.start();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());//打印出当前线程的名字
t1.interrupt();
System.out.println("000000");
}
t1
false
开始睡觉
main
000000
Interrupted When Sleep!
false
让出资源
t1 Interrupted!
上一篇:RestFul WebAPI