java基础知识回顾之java Thread类学习(十二)-- 线程中断
官方文档翻译:
如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long),
join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。若线程在阻塞状态时,调用了它的interrupt()方法,那么
它的“中断状态”会被清除并且会收到一个InterruptedException异常。例如,线程通过wait()进入阻塞状态,此时通过interrupt()中断该线程;
调用interrupt()会立即将线程的中断标记设为“true”,但是由于线程处于阻塞状态,所以该“中断标记”会立即被清除为“false”,同时,会产生一个InterruptedException的异常。
如果线程被阻塞在一个Selector选择器中,那么通过interrupt()中断它时;线程的中断标记会被设置为true,并且它会立即从选择操作中返回。
如果不属于前面所说的情况,那么通过interrupt()中断线程时,它的中断标记会被设置为“true”。中断一个“已终止的线程”不会产生任何操作。
线程处于“阻塞状态”和“运行状态”的终止方式如下:
(1)使用isInterrupted判断,使用interrupt中断
@Override public void run() { try { // 1. isInterrupted()保证,只要中断标记为true就终止线程。 while (!isInterrupted()) { // 执行任务... } } catch (InterruptedException ie) { // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。 } }
例子1:
package concurrentMy.interrupts; /** * * (interrupt()常常被用来终止“阻塞状态”线程。) * * <p> * 修改历史: <br> * 修改日期 修改人员 版本 修改内容<br> * -------------------------------------------------<br> * 2016年11月3日 下午2:56:44 user 1.0 初始化创建<br> * </p> * * @author Peng.Li * @version 1.0 * @since JDK1.7 * 运行结果: A线程的状态: (NEW) is new A线程的状态: (RUNNABLE) is start A线程的状态: (RUNNABLE) loop 1 A线程的状态: (RUNNABLE) loop 2 A线程的状态: (TIMED_WAITING) is interrupted A线程的状态: (RUNNABLE) catch InterruptedException. A线程的状态: (TERMINATED) is interrupted now 结果说明:1.主线程通过 new ThreadMy("A")创建线程t1,之后之后通过t1.start()启动线程A。 2.线程A启动之后,会不断的检查它的中断标识,如果中断标识为false,则休眠100ms 3.t1休眠之后,会切换到主线程main,主线程再次运行,会执行t1.interrupt();中断A线程, A收到中断指令后,将A线程的中断标识设置成“false”,而且会抛出InterruptedException异常 * */ class ThreadMy extends Thread { public ThreadMy(String name) { super(name); } @Override public void run() { int i = 0; try { //1. isInterrupted()保证,只要中断标记为true就终止线程。 while (!isInterrupted()) { //线程A休眠,进入阻塞状态 Thread.sleep(100); i++; // 返回当前线程的状态 System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") loop " + i); } } catch (InterruptedException e) { // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。 // TODO: handle exception System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") catch InterruptedException."); } } } public class Demo1_interrupt { public static void main(String[] args) { try { // 新建线程A ThreadMy t1 = new ThreadMy("A"); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is new"); // 启动线程A t1.start(); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is start"); // 主线程休眠300毫秒,然后main线程给t1发送指令 Thread.sleep(300); t1.interrupt(); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted"); // 主线程再休眠300ms,查看A线程的状态 Thread.sleep(300); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted now"); } catch (InterruptedException e) { e.printStackTrace(); } } }
(2)安全的终止线程,使用volatile boolean变量。
package concurrentMy.interrupts; /** * * * <p> * 修改历史: <br> * 修改日期 修改人员 版本 修改内容<br> * -------------------------------------------------<br> * 2016年11月3日 下午2:56:44 user 1.0 初始化创建<br> * </p> * * @author Peng.Li * @version 1.0 * @since JDK1.7 * 安全的终止线程,使用volatile boolean变量。 运行结果: A线程的状态: (NEW) is new A线程的状态: (RUNNABLE) is start A线程的状态: (RUNNABLE) loop 1 A线程的状态: (RUNNABLE) loop 2 A线程的状态: (TIMED_WAITING) is interrupted A线程的状态: (RUNNABLE) loop 3 count3 A线程的状态: (TERMINATED) is interrupted now 结果说明:1.主线程通过 new ThreadMy("A")创建线程t1,之后之后通过t1.start()启动线程A。 2.线程A启动之后,会不断的检查它的中断标识,如果中断标识为true,则休眠100ms 3.t1休眠之后,会切换到主线程main,主线程再次运行,会执行t1.cancel();中断A线程, A收到中断指令后,将A线程的中断标识设置成“false”,清除中断标识,而且会抛出InterruptedException异常 * * * */ class ThreadMy1 extends Thread { // volatile的应用,保证线程之间对on标识的可见性,一个线程(主线程)改了标识, // 即调用A线程的cancel方法取消或者停止了任务(A线程的执行,则立即对这个线程(A线程)可见 private volatile boolean on = true; public ThreadMy1(String name) { super(name); } /** * * (// 通过on 变量来控制是否需要停止任务并且终止任务) * */ public void cancel() { on = false; } @Override public void run() { int i = 0; try { // on = false 的时候中断线程 while (on /* && !isInterrupted() */) { // 线程A休眠,进入阻塞状态 Thread.sleep(100); i++; // 返回当前线程的状态 System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") loop " + i); } System.out.println("count" + i); } catch (InterruptedException e) { // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止,这个地方加一些日志操作 // TODO: handle exception System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") catch InterruptedException."); } } } public class Demo2_interrupt { public static void main(String[] args) { try { // 新建线程A ThreadMy1 t1 = new ThreadMy1("A"); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is new"); // 启动线程A t1.start(); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is start"); // 主线程休眠300毫秒,然后main线程给t1发送指令 Thread.sleep(300); // 中断线程 t1.cancel(); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted"); // 主线程再休眠300ms,查看A线程的状态 Thread.sleep(300); System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted now"); } catch (InterruptedException e) { e.printStackTrace(); } } }
Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear.
面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!