线程中断 interrupt 方法怎么理解,意思就是线程中断了吗?那当前线程还能继续执行吗?
判断线程是否中断的方法有几个,它们之间有什么区别?
LockSupport的 park/unpark 和 wait/notify 有什么区别?
sleep 方法是怎么响应中断的?
park 方法又是怎么响应中断的?
线程中断相关方法线程中和中断相关的方法有三个,分别介绍如下:
1) interrupt
我们一般都说这个方法是用来中断线程的,那么这个中断应该怎么理解呢? 就是说把当前正在执行的线程中断掉,不让它继续往下执行吗?
其实,不然。 此处,说的中断仅仅是给线程设置一个中断的标识(设置为true),线程还是会继续往下执行的。而线程怎么停止,则需要由我们自己去处理。 一会儿会用代码来说明这个。
2) isInterrupted
判断当前线程的中断状态,即判断线程的中断标识是true还是false。 注意,这个方法不会对线程原本的中断状态产生任何影响。
3) interrupted
也是判断线程的中断状态的。但是,需要注意的是,这个方法和 isInterrupted 有很大的不同。我们看下它们的源码:
public boolean isInterrupted() { return isInterrupted(false); } public static boolean interrupted() { return currentThread().isInterrupted(true); } //调用同一个方法,只是传参不同 private native boolean isInterrupted(boolean ClearInterrupted);首先 isInterrupted 方法是线程对象的方法,而 interrupted 是Thread类的静态方法。
其次,它们都调用了同一个本地方法 isInterrupted,不同的只是传参的值,这个参数代表的是,是否要把线程的中断状态清除(清除即不论之前的中断状态是什么值,最终都会设置为false)。
因此,interrupted 静态方法会把原本线程的中断状态清除,而 isInterrupted 则不会。所以,如果你调用两次 interrupted 方法,第二次就一定会返回false,除非中间又被中断了一次。
下面证明一下 interrupt 方法只是设置一个中断状态,而不是使当前线程中断运行:
public class TestFlag { static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new Runnable(){ @Override public void run() { System.out.println("线程中断标志:"+Thread.currentThread().isInterrupted()); while (flag){ } System.out.println("标志flag为:" + flag); System.out.println("线程中断标志:"+Thread.currentThread().isInterrupted()); System.out.println("我还在继续执行"); } }); t.start(); Thread.sleep(100); flag = false; t.interrupt(); } }运行结果:
线程中断标志:false 标志flag为:false 线程中断标志:true 我还在继续执行当线程启动,还没调用中断方法时,中断状态为false,然后调用中断方法,并把flag设置为false。此时,run方法跳出while死循环。我们会发现线程的中断状态为true,但是线程还是会继续往下执行,直到执行结束。
sleep 响应中断线程中常用的阻塞方法,如sleep,join和wait 都会响应中断,然后抛出一个中断异常 InterruptedException。但是,注意此时,线程的中断状态会被清除。所以,当我们捕获到中断异常之后,应该保留中断信息,以便让上层代码知道当前线程中断了。通常有两种方法可以做到。
一种是,捕获异常之后,再重新抛出异常,让上层代码知道。另一种是,在捕获异常时,通过 interrupt 方法把中断状态重新设置为true。
下面,就以sleep方法为例,捕获中断异常,然后重新设置中断状态:
public class TestInterrupt { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new Runnable() { private int count = 0; @Override public void run() { try { count = new Random().nextInt(1000); count = count * count; System.out.println("count:"+count); Thread.sleep(5000); } catch (Exception e) { System.out.println(Thread.currentThread().getName()+"线程第一次中断标志:"+Thread.currentThread().isInterrupted()); //重新把线程中断状态设置为true,以便上层代码判断 Thread.currentThread().interrupt(); System.out.println(Thread.currentThread().getName()+"线程第二次中断标志:"+Thread.currentThread().isInterrupted()); } } }); t.start(); Thread.sleep(100); t.interrupt(); } }结果:
count:208849 Thread-0线程第一次中断标志:false Thread-0线程第二次中断标志:true LockSupport方法介绍LockSupport 方法中重要的两个方法就是park 和 unpark 。
park和interrupt中断
park方法可以阻塞当前线程,如果调用unpark方法或者中断当前线程,则会从park方法中返回。