目录
有些业务场景下,我们启动线程后又不想让它执行下去,就需要中断线程。所以Java中提供了线程中断机制来处理需要中断线程的情况。
注意:Java中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止线程,而是被中断的线程会根据这个标志自行处理。
线程中断的几个方法:
1、void interrupt()
这个方法是通过设置中断标志来中断线程,但是这个标志仅仅只是个标志,并不代表能直接终止线程,此时线程还会继续往下执行。如果被中断的线程有调用wait()方法、join()方法、sleep()方法,那么就会在调用的地方抛出InterruptedException异常而返回。
public 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();
}
2、boolean isInterrupted()
这个方法是检测当前线程是否被中断,返回true或false。底层调用isInterrupted()方法,传递参数false表示不清除中断标志。
public boolean isInterrupted() {
// 传递参数false表示不清除中断标志
return isInterrupted(false);
}
3、boolean interrupted()
这个方法也是检测当前线程是否被中断,不过跟上面方法的不同之处就是此方法调用会清除中断标志,也就是底层调用isInterrupted()方法,传递参数true表示清除中断标志,并且该方法是static方法,可以使用Thread直接调用。从下面的代码也可以看出,内部是获取当前线程的中断标志而不是调用这个方法的实例对象的中断标志。
public static boolean interrupted() {
// 清除中断标志
return currentThread().isInterrupted(true);
}
我们可以通过一段代码来了解一下 isInterrupted()方法和interrupted()方法的不同之处。
public class InterruptedAndIsInterrupted {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread (()->{
for (;;){
}
});
//启动线程
thread.start ();
// 设置子线程中断标志
thread.interrupt ();
// 获取子线程中断标志,所以为true
System.out.println ("中断标志为:"+thread.isInterrupted ());
// 获取中断标志并清除中断标志,这个方法因为获取的是当前线程的中断标志,也就是main线程,所以为false
System.out.println ("中断标志为:"+Thread.interrupted ());
// 这里当前线程是主线程main,设置中断标志
Thread.currentThread ().interrupt ();
// 重复调用interrupted()会修改中断状态,也就是清除了中断标志,所以第一个是true,第二个为false
System.out.println ("当前线程中断标志为:"+Thread.interrupted ());
System.out.println ("当前线程中断标志为:"+Thread.interrupted ());
// 获取子线程中断标志,因为此方法不清楚中断标志,所以为true
System.out.println ("中断标志为:"+thread.isInterrupted ());
thread.join ();
System.out.println ("main thread is over");
}
}
输出结果:
中断标志为:true
中断标志为:false
当前线程中断标志为:true
当前线程中断标志为:false
中断标志为:true
4、栗子
举个栗子,根据中断标志判断线程是否终止。一起来瞧一瞧。
public class InterruptedTest {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread (new Runnable () {
@Override
public void run() {
// 中断标志为true时会退出循环,并且清除中断标志
while (!Thread.currentThread ().isInterrupted ()) {
System.out.println (1);
}
System.out.println ("thread isInterrupted:" + Thread.currentThread ().isInterrupted ());
}
});
// 启动子线程
thread.start ();
// 休眠主线程,中断前让子线程输出
Thread.sleep (100);
// 设置子线程中断标志
thread.interrupt ();
// 等待子线程执行完毕
thread.join ();
System.out.println ("main is over");
}
}
输出结果:
1
thread isInterrupted:true
main is over
上面代码中的子线程通过设置中断标志来处理是否退出循环,主线程在子线程中断之前休眠一段时间,这样子线程就能退出循环并输出。
5、总结
在线程中断机制里,当其他线程通知需要被中断的线程后,线程中断的状态被设置为true,但是具体被要求中断的线程要怎么处理,完全由被中断线程自己而定,可以在合适的实际处理中断请求,也可以完全不处理继续执行下去。