线程中断理解
来源:互联网 发布:均值漂移算法原理 编辑:程序博客网 时间:2024/06/16 08:01
无法中断的线程
package objective1.action2;public class InterruptHandler { public static void main(String[] args) { Runnable runnable = new InterruptRunner(); Thread thread = new Thread(runnable); thread.start(); thread.interrupt(); }}class InterruptRunner implements Runnable { @Override public void run() { int i = 0; while (true) { System.out.println("i=" + i++); } }}
该例子尝试使用用interrupt中断线程,但interrupt方法并不像break方法一样,马上停止循环,而是持续对i增加,不会停止。
中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行了中断操作。中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt()
方法对其进行中断操作。
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(); }
从上面源码中也可与看出,interrupt只是在当前线程中打了个停止标志。
那么如何才能停止线程呢?
可以在该线程中观察中断标志状态,如果中断标志状态显示中断,就可以在该线程中执行中断。
判断线程中断的状态
Thread提供了两种方法判断线程中断状态。
public static boolean interrupted() public boolean isInterrupted()
两个方法有什么区别呢?
interrupted方法: 测试当前线程是否已经是中断状态,并清除标志位
isInterrupted方法:测试当前线程是否已经是中断状态,不清除标志位
- isInterrupted()方法
public class InterruptHandler2 { public static void main(String[] args) { Thread thread = new InterruptThread(); thread.start(); thread.interrupt(); }}class InterruptThread extends Thread { @Override public void run() { System.out.println("停止状态1:" + Thread.currentThread().isInterrupted()); System.out.println("停止状态2:" + Thread.currentThread().isInterrupted()); System.out.println("停止状态3:" + Thread.currentThread().isInterrupted()); }}
停止状态1:true停止状态2:true停止状态3:true
可以看出isInterrupted()判断状态后,再次判断中断状态仍然是true,没有清除中断标志位。
- interrupted方法
public class InterruptHandler2 { public static void main(String[] args) { Thread thread = new InterruptThread1(); thread.start(); thread.interrupt(); }}class InterruptThread1 extends Thread { @Override public void run() { System.out.println("停止状态1:" + Thread.interrupted()); System.out.println("停止状态2:" + Thread.interrupted()); System.out.println("停止状态3:" + Thread.interrupted()); }}
停止状态1:true停止状态2:false停止状态3:false
可以看出interrupted()判断状态后,再次判断中断状态全是false,说明将标志位恢复了。
- 源码分析
观察Thread源码,发现这两个方法最终都是调用 isInterrupted(boolean ClearInterrupted),不同的只是interrupted()默认将清除中断标志位设成true.
public boolean isInterrupted() { return isInterrupted(false); }
public static boolean interrupted() { return currentThread().isInterrupted(true); }
private native boolean isInterrupted(boolean ClearInterrupted);
停止线程的方法
使用异常停止
使用break停止
判断中断标志位,当标志位被置为中断时,使用break中断。虽然中断了while循环但是,还是继续往下执行了,也就是说线程没有立即停止。
public class InterruptHandler { public static void main(String[] args) { System.out.println("start"); Runnable runnable = new InterruptRunner(); Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); System.out.println("end"); }}class InterruptRunner implements Runnable { @Override public void run() { int i = 0; while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("已经是中断状态了,我要退出了"); break; } System.out.println("我还没中断 i=" + i++); } System.out.println("我在while下面!我被执行说明break后代码继续运行,线程没有立即停止"); }}
....我还没中断 i=3end已经是中断状态了,我要退出了我在while下面!我被执行说明break后代码继续运行,线程没有立即停止
使用在sleep中catch异常停止
public class InterruptHandler { public static void main(String[] args) { System.out.println("start"); Runnable runnable = new InterruptRunner(); Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); System.out.println("end"); }}class InterruptRunner implements Runnable { @Override public void run() { int i = 0; try { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("已经是中断状态了,我要退出了"); Thread.sleep(100); } System.out.println("我还没中断 i=" + i++); } } catch (InterruptedException e) { System.out.println("中断标志" + Thread.currentThread().isInterrupted()); System.out.println("进入" + Thread.currentThread().getName() + "的exception方法,然后中断"); System.out.println(e); Thread.currentThread().interrupt(); } }}
我还没中断 i=19end已经是中断状态了,我要退出了catch exception后中断标志false进入Thread-0的exception方法,然后中断java.lang.InterruptedException: sleep interrupted
可以看出在线程sleep时候,存在中断操作会抛出InterruptedException ,并且将清除中断标志位停止状态。而这时若catch住异常,并对线程执行interrupt操作,就可以达到中断线程的效果。
Q:那么为什么在线程sleep的时候,执行中断操作(或中断时候执行sleep)会抛出异常呢?
当thread被阻塞的时候,比如被Object.wait,Thread.join和Thread.sleep三种方法之一阻塞时。调用它的interrput()方法。 可想而知,没有占用CPU运行的线程是不可能给自己的中断状态置位的。这就会产生一个InterruptedException异常。
使用抛出异常在外面catch停止
public class InterruptHandler { public static void main(String[] args) { System.out.println("start"); Runnable runnable = new InterruptRunner(); Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); System.out.println("end"); }}class InterruptRunner implements Runnable { @Override public void run() { int i = 0; try { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("已经是中断状态了,我要退出了"); throw new InterruptedException(); } System.out.println("我还没中断 i=" + i++); } } catch (InterruptedException e) { System.out.println("中断标志" + Thread.currentThread().isInterrupted()); System.out.println("进入" + Thread.currentThread().getName() + "的exception方法,然后中断"); System.out.println(e); } }}
我还没中断 i=57end已经是中断状态了,我要退出了中断标志true进入Thread-0的exception方法,然后中断java.lang.InterruptedException
如上例子判断中断标志位为true时,立即将异常抛出,并在外层处理达到线程停止。这样做的好处是,还可以将异常往外抛,使线程停止的事件得以传播。
使用return的方法停止
public class InterruptHandler { public static void main(String[] args) { System.out.println("start"); Runnable runnable = new InterruptRunner(); Thread thread = new Thread(runnable); thread.start(); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); System.out.println("end"); }}class InterruptRunner implements Runnable { @Override public void run() { int i = 0; while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("已经是中断状态了,我要退出了"); return; } System.out.println("我还没中断 i=" + i++); } }}
start我还没中断 i=0end已经是中断状态了,我要退出了
可以看出,其实和用异常方法停止线程没有本质区别,都是在判断中断标志位被设置为true时,进行退出操作。
使用过期的stop方法停止
stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。不建议使用。
- 线程中断理解
- 理解Java线程的中断
- 理解Java线程的中断
- 理解Java线程的中断
- java线程中断的理解
- java线程的中断理解
- Java线程中断的本质深入理解
- Java 基本功 之中断线程的理解
- Java线程中断理解(interrupte)
- 理解java线程的中断(interrupt)
- Java线程中断的本质深入理解
- 【转】理解java线程的中断(interrupt)
- 理解java线程的中断(interrupt)
- 中断线程 —— interrupt() 以及对其理解
- 线程中断
- 中断线程
- 中断线程
- 中断线程
- tomcat自动部署代码脚本
- linux011-unstd.h头文件
- uboot移植第四天——代码分析(4)
- 略读《Effective C++》摘要
- ARM基础学习-SWI异常中断处理
- 线程中断理解
- 数据结构-树
- 作业4
- Linux下C/C++帮助手册安装方法
- android 接口回调的简单实现
- Volley 源码解析
- 杭电1242-Rescue-DFS
- ubuntu安装mysql
- 水平垂直居中