我认为代码很容易解释这个问题。下面将进行总结。
点击此处或向下阅读总结:
直接来一个小代码吧:
public class Interrupt { public static void main(String[] args) { Thread t = new Thread(new Worker()); t.start(); try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t.interrupt(); System.out.println("Main thread stopped."); } public static class Worker implements Runnable { public void run() { System.out.println("Worker started."); boolean f; // 用于检测interupted()的第一次返回值 int i = 0; Thread c = Thread.currentThread(); System.out.println(isinterupted()while之前的线程中断状态:" + c.isInterrupted()); while (!(f = Thread.interrupted())) {// 判断是否中断,如果中断,跳出并清除中断标志位置 // 一旦检测到中断,interrupted()第一次回到true,就可以跳出循环,第二次和以后都会回到falsee System.out.println(while内,还没有中断,interrupted()返回值为:"" + f); System.out.println(c.getName() + " " + i++ + " " + c.isInterrupted()); } System.out.println(”跳出循环是Interupted()返回值的第一次中断 + f); System.out.println(isinterupted():" + c.isInterrupted()); // 为false,因为interrupt()会清除中断标志位,显示为未中断 System.out.println(interupted()第二次及以后的返回值:" + Thread.interrupted()); c.interrupt(); System.out.println()再次中断后,查询isinterupted():" + c.isInterrupted()); System.out.println("Worker stopped."); } }}
运行结果:
...省略一些相同的步骤
分析说明:
interrupt()用于中断线程,调用该方法的线程状态将被放置为“中断”状态。注意:线程中断只是设置线程的中断状态,不会停止线程。用户需要监控线程的状态并进行处理。在这里,我们可以看到线程在中断后继续下降,并且没有强制终止线程。
为什么主线程执行t?.interrupt()然后调用isinterupt()返回false?
因为在这里调用interupted()将清除中断标志位。
另一种情况:如果线程在wait, sleep,join受阻时,调用interupt()方法,不仅会清除中断标志位,还会抛出interuptedException异常。这个例子最后会在下面给出。
让我们来看看interupted()和isinterupted()
public static boolean interrupted() { return currentThread().isInterrupted(true); }public boolean isInterrupted() { return isInterrupted(false); } private native boolean isInterrupted(boolean ClearInterrupted);
这是一种看不到源代码的native方法,但注意表明,如果输入false,中断标志位不会被删除,如果输入true,中断标志位将被删除。
isInterrupted ()非常诚实,只查询中断标志位,不改变中断标志位。
如果线程在wait, sleep,join受阻时,调用interupt()方法,不仅会清除中断标志位,还会抛出InteruptedException异常。
然后给出另一个例子。
public class Interrupt { public static void main(String[] args) throws Exception { Thread t = new Thread(new Worker()); t.start(); Thread.sleep(100); t.interrupt(); System.out.println("Main thread stopped."); } public static class Worker implements Runnable { public void run() { System.out.println("Worker started."); try { Thread.sleep(500); // 此时,Interupt()将抛出Interuptedexception } catch (InterruptedException e) { Thread thread = Thread.currentThread(); System.out.println(isinterupted()在再次中断之前:" + thread.isInterrupted()); System.out.println(interupted()在再次中断之前:" + Thread.interrupted()); // 再次调用interrupt方法中断自己,将中断状态设置为“中断” thread.interrupt(); System.out.println(isinterupt()后isinterupted():" + thread.isInterrupted()); System.out.println(”interupt()再次interupt()后第一次interupted()返回:" + Thread.interrupted());// clear status // interrupted()判断是否中断,中断标志位也将被清除 System.out.println("interrupted()此时,判断ISInterupted: " + thread.isInterrupted()); System.out.println("---------After Interrupt Status Cleared----------"); System.out.println((interupt()再次interupt()后第二次interupted()返回: " + Thread.interrupted()); System.out.println(此时,判断ISInterupted: " + thread.isInterrupted()); } System.out.println("Worker stopped."); } }}
运行结果:
interrupt()方法
如果sleep不中断,wait,如果join方法或文档中描述的其他情况,则不会抛出interuptexception异常,也不会清除中断标志位,isInterrupt()返回true。
若中断sleep,wait,join等,会抛出interruptexception异常,会清除中断标志位,isInterrupt()返回false。
interrupted()方法
第一次使用返回true并清除中断标志位后,查询中断状态isinterupt()将返回false。刚才第一个例子也看到了,用了 第一次返回的true可以跳出循环。第二次和以后都是返回false。
isInterrupted()方法
查询中断标志位,判断是否中断并返回true或false。
若中断sleep,wait,join等。,会抛出interuptexception异常,中断标志位将被清除。那么这种情况应该怎么处理呢?为了保证数据的一致性和完整性,我们需要使用thread.interrupt()方法再次中断自己,设置中断标志位。例子如下:
public class test { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread() { public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("Interruted!"); break; } try { Thread.sleep(2000); // 睡眠中断会清除中断标志 } catch (InterruptedException e) { // 如果没有下面这句话,虽然这个线程在外面中断,但只要睡眠过程中断 // 中断标志位将被清除,仍处于无限循环,CPU资源将竞争 Thread.currentThread().interrupt(); // 再次中断上中断标记 } Thread.yield(); } } }; t1.start(); Thread.sleep(200); t1.interrupt(); }}
Thread.sleep()该方法因中断而抛出异常。此时,它将清除中断标记。如果不处理,则在下一个循环开始时无法捕获中断。因此,在异常处理中,中断标记位置将再次设置。
下面给出官方文件说明:
interrupt
public void interrupt()
中断线程。
如果当前线程没有中断自己(这在任何情况下都是允许的),则调用该线程的checkaccess方法,可能会抛出securityexception。
如果线程正在调用Objectwait()、wait(long)或wait(long, int)方法,或者这种join()、join(long)、join(long, int)、sleep(long)或sleep(long, int)如果在方法过程中受阻,中断状态将被清除,它还将收到InteruptedException。
如果线程在可中断通道上 I/O 如果操作中受阻,通道将关闭,线程的中断状态将设置,线程将收到ClosedByinteruptexception。
如果该线程在Selector中受阻,则将设置该线程的中断状态。它将立即从选择操作返回,并可能具有非零值,就像调用选择器的wakeup方法一样。
若以前的条件未保存,则将设置线程的中断状态。
不处于活动状态的线程中断不需要任何效果。
抛出:
SecurityException
- 如果当前线程不能修改该线程
interrupted
public static boolean interrupted()
测试当前线程是否中断。线程中断状态这种方法被清除了。换句话说,如果该方法连续调用两次,第二次调用将返回 false(第一次调用清除中断状态后,第二次调用检查中断状态前,当前线程再次中断的除外)。
由于中断时不处于活动状态的线程会返回,因此忽略了线程中断。 false 方法反映出来。
返回:
如果当前线程中断,则返回true
;否则返回false
。
另请参见:
isInterrupted()
isInterrupted
public boolean isInterrupted()
测试线程是否中断。线程中断状态不受该方法的影响。
由于中断时不处于活动状态的线程会返回,因此忽略了线程中断。 false 方法反映出来。
返回:
如果该线程中断,则返回true
;否则返回false
。
另请参见:
interrupted()
