interrupt、interrupted 、isInterrupted、InterruptedException

本文详细解析Java中线程的中断机制,包括interrupt方法的作用、interrupted与isInterrupted的区别,以及InterruptedException的处理方式。

interrupt

interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态并做处理。
如果目标线程当前正在执行某些可能阻塞的操作(如 Thread.sleep(), Object.wait(), 或者 I/O 操作等),那么调用 interrupt() 会使得这些方法抛出 InterruptedException.

interrupted 和 isInterrupted

interruptted实现:
public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
 
该方法就是直接调用当前线程的isInterrupted(true)方法。
isInterrupted实现:
public boolean isInterrupted() {
        return isInterrupted(false);
    }
这两个方法有两个主要区别:
  1. interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。)
  2. 这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;
第二个区别主要体现在调用的方法的参数上,让我们来看一看这个参数是什么含义
先来看一看被调用的方法 isInterrupted(boolean arg)的定义:
private native boolean isInterrupted(boolean ClearInterrupted);
原来这是一个本地方法,看不到源码。通过参数名我们就能知道,这个参数代表是否要清除状态位。

如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位。这个参数为false,就是直接返回线程的状态位。

也就是interrupted返回线程的状态位,又清空了状态位。isInterrupted只是返回了线程的状态位

以下程序看这三个方法的区别:

public class ThreadInterruptTest {
	public static void main(String[] args) {
		
		System.out.println("isInterrupted :"  + Thread.currentThread().isInterrupted());//当前线程没有被中断,返回false;
		Thread.currentThread().interrupt();//中断了该线程,但是该线程仍会继续执行,该方法只是将线程的状态设置成“中断”状态
		System.out.println("isInterrupted :" + Thread.currentThread().isInterrupted());//interrupt()执行后,线程被设置成中断状态,返回true
		System.out.println("interrupted :" + Thread.interrupted());//返回了中断状态:true,又清掉了状态位。
		System.out.println("isInterrupted :" + Thread.currentThread().isInterrupted());//由于interrupted()清掉了状态位,所以返回false;
		System.out.println("interrupted :" + Thread.interrupted());//返回false
	}
}

执行结果:

InterruptedException

当一个线程被一些声明了InterruptedException的方法阻塞时,你对这个线程调用Thread.interrupt(),那么大多数这样的方法会立即抛出InterruptedException.如果有些人试着去打断我们的线程,而我们通过捕捉InterruptedException发现了它,这时候最合理的事情就是结束上述被打断的线程(然而大多数时候我们并不处理它)。
public class InterruptedExceptionTest {
	
	public static void main(String[] args) throws InterruptedException {
		ThreadA a = new ThreadA();
		a.start();
		Thread.sleep(2000);
		a.interrupt();
		System.out.println("a:" + a.isInterrupted());
	}
	

}

class ThreadA extends Thread {

	@Override
	public void run() {
		while (!Thread.currentThread().isInterrupted()) {
			System.out.println("正在执行");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {//状态位被清除
				e.printStackTrace();
				System.out.println("该线程:" + Thread.currentThread().isInterrupted());//由于状态位被清除,返回false
				Thread.currentThread().interrupt();
			}
		}
	}
	
}

上面的程序中,主线程调用了a线程的interrupt()方法(线程a的状态位被置为"中断"),线程a捕获了InterruptedException后(此时,线程a的“中断”状态被清除),调用了Thread.currentThread().interrupt(),线程a的状态被置为“中断”,接着继续执行循环条件,线程是中断状态,跳出了循环,线程最终结束了执行。这里,如果在捕获InterruptedException后,不将线程的状态置为“中断”,那么循环仍然会执行,并不会结束。
注意一下几点:
  • 捕获InterruptedException之后应该适当地对它进行处理-大多数情况下适当的处理指的是完全地跳出当前任务/循环/线程。
  • 吞掉InterruptedException不是一个好主意
  • 如果线程在非阻塞调用中被打断了,这时应该使用isInterrupted()。当线程早已被打断(也就是被标记为interrupted)时,一旦进入阻塞方法就应该立刻抛出InterruptedException。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值