2. 异常法停止线程
(1) 线程循环中正常退出停止
退出方法 : 正常退出线程;
-- 1. 前提 : 线程中执行一个循环;
-- 2. 中断线程 : 执行线程中断操作, 调用 线程的 interrupt() 方法;
-- 3. 查询中断标志 : 在线程中通过调用 interrupted 方法, 查询当前的线程中断标志, 之后该方法就会将中断标志清除;
-- 4. 退出循环 : 如果查询到中断标志后, 直接使用 break 退出循环;
-- 5. 弊端 : 在线程中, 线程没有真正的停止, 线程还是完整的执行了;
线程正常退出代码示例 :
-- 1. 代码 :
public class ExceptionInterruptDeo { public static class MyThread extends Thread{ @Override public void run() { super.run(); for(int i = 0; i < 500; i ++){ if(interrupted()){ //判断线程的中断状态, 如果中断直接 break System.out.println("停止状态, 退出"); break; } System.out.println(i); } System.out.println("MyThread 线程执行完毕");//线程结束标志 } } public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); //创建线程并执行 thread.start(); //启动线程 Thread.sleep(1); //沉睡 1 毫秒 thread.interrupt(); //中断线程 System.out.println("主线程执行完毕"); //判断主线程停止 } }
-- 2. 执行结果 :
... ... 50 51 52 53 54
主线程执行完毕
停止状态, 退出
MyThread 线程执行完毕
-- 3. 总结分析 : 在线程中调用 interrupted() 方法, 查询中断标志(查询后立即清除中断标志), 弊端是停止线程后, 线程还是继续执行后面的逻辑, 继续执行完毕, 自动退出的;
(2) 异常退出线程
异常法退出线程 : 通过抛出一个异常, 来终止线程执行;
-- 1. 前提 : 线程中执行一个循环;
-- 2. 中断线程 : 执行线程中断操作, 调用 线程的 interrupt() 方法;
-- 3. 查询中断标志 : 在线程中通过调用 interrupted 方法, 查询当前的线程中断标志, 之后该方法就会将中断标志清除;
-- 4. 抛出异常退出循环 : 如果查询到中断标志后, 直接抛出一个 InterruptException 异常;
-- 5. 捕获处理异常 : 要将整个 run 方法中的内容使用 try catch 代码块捕获, 因因为异常捕获后还会继续处理 try catch 之后的代码逻辑, 如果 try catch 代码块之后还有代码逻辑, 程序还会执行这段代码;
-- 6. 好处 : 可以自由控制要中断哪些逻辑;
异常捕获规则 :
-- 1. 执行逻辑 : 捕获异常后, 进行异常处理, 然后会继续执行 try catch 代码块 后面的代码逻辑;
-- 2. 异常退出范围可控 : 可以自由控制中断哪些操作, 继续执行哪些操作;
代码测试 :
-- 1. 代码 :
public class ExceptionInterruptDeo { public static class MyThread extends Thread { @Override public void run() { try { super.run(); for (int i = 0; i < 500; i++) { if (interrupted()) { // 判断线程的中断状态, 如果中断直接 break System.out.println("停止状态, 抛出异常退出"); throw new InterruptedException(); }// 中断标志 判定结束 System.out.println(i); }//for 循环结束 System.out.println("MyThread 线程执行完毕");// 线程结束标志 } catch (InterruptedException e) { System.out.println("线程中捕获异常代码块"); e.printStackTrace(); } // try catch 代码块 }//run方法结束 }//线程结束 public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); // 创建线程并执行 thread.start(); // 启动线程 Thread.sleep(1); // 沉睡 1 毫秒 thread.interrupt(); // 中断线程 System.out.println("主线程执行完毕"); // 判断主线程停止 } }
-- 2. 执行结果 :
113 114 115 116
主线程执行完毕
停止状态, 抛出异常退出
线程中捕获异常代码块
java.lang.InterruptedException
at base.ExceptionInterruptDeo$MyThread.run(ExceptionInterruptDeo.java:12)
-- 3. 总结分析 : 在 run 方法中将整个代码逻辑使用 try catch 代码块包裹, 异常法只能中断 try catch 代码块中的逻辑;
3. sleep() 中停止线程
(1) 先沉睡在终止线程
先 sleep() 再 interrupt() : 先沉睡, 再终止线程, 线程直接就停止了;
代码示例 :
-- 1. 代码 :
public class SleepInterruptDemo { public static class MyThread extends Thread{ @Override public void run() { try { System.out.println("线程逻辑开始"); super.run(); sleep(1000); //启动后立即进入沉睡状态, 沉睡 1000ms System.out.println("线程逻辑结束"); } catch (InterruptedException e) { System.out.println("捕获到了异常 , 进入了 catch 代码块"); e.printStackTrace(); }//catch代码块 System.out.println("run 方法结束"); }//run方法 }//线程 public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); //新建线程 thread.start(); //线程启动 Thread.sleep(100); //沉睡 100 毫秒, 线程中 thread.interrupt(); //中断线程 } }
-- 2. 执行结果 :
线程逻辑开始 捕获到了异常 , 进入了 catch 代码块 run 方法结束 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at base.SleepInterruptDemo$MyThread.run(SleepInterruptDemo.java:11)
-- 3. 总结分析 : 在沉睡状态下, 如果调用 interrupt() 方法, 线程中会直接抛出 InterruptException 异常;
(2) 先终止线程 再 沉睡
先 终止线程 再 sleep : 先 终止线程, 在 sleep, 那么 sleep 之前的代码需要实现相关逻辑
代码示例 :
-- 1. 代码 : 与上面的区别是 在 sleep 之前有一段 循环逻辑;
public class SleepInterruptDemo { public static class MyThread extends Thread{ @Override public void run() { try { System.out.println("线程逻辑开始"); super.run(); for(int i = 0; i < 500; i ++) System.out.println(i); sleep(1000); //启动后立即进入沉睡状态, 沉睡 1000ms System.out.println("线程逻辑结束"); } catch (InterruptedException e) { System.out.println("捕获到了异常 , 进入了 catch 代码块"); e.printStackTrace(); }//catch代码块 System.out.println("run 方法结束"); }//run方法 }//线程 public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); //新建线程 thread.start(); //线程启动 thread.interrupt(); //中断线程 System.out.println("主线程中断线程"); } }
-- 2. 执行结果 :
496 497 498 499
捕获到了异常 , 进入了 catch 代码块
run 方法结束
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at base.SleepInterruptDemo$MyThread.run(SleepInterruptDemo.java:12)
-- 3. 总结 : 使用 Interrupt 方法后, 如果正在执行循环, 就不会抛异常退出线程, 进入 sleep 状态后, 会立即抛出异常, 退出线程;
4. stop() 停止线程
(1) stop 方法停止线程的效果
stop 停止线程 :
-- 1. 立即停止 : 调用 stop() 方法停止线程, 比较暴力, 会立即停止当前的线程;
-- 2. 抛出异常 : 使用 stop() 方法停止线程会抛出一个 ThreadDeath 异常, 这个异常可以不捕捉;
-- 3. 适用场景 : 适用该方法停止线程, 前提示 线程的相关数据 和 线程本身 都不再使用了, 否则会造成数据混乱;
stop() 停止线程效果演示 :
-- 1. 代码示例 :
public class StopDemo { public static class MyThread extends Thread{ @Override public void run() { try { System.out.println("线程逻辑开始"); super.run(); for(int i = 0; i < 5000; i ++){ System.out.println(i); sleep(100); } System.out.println("线程逻辑结束"); } catch (InterruptedException e) { System.out.println("捕获到了 InterruptedException 异常 , 进入了 catch 代码块"); e.printStackTrace(); }//catch代码块 System.out.println("run 方法结束"); }//run方法 }//线程 public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); //新建线程 thread.start(); //线程启动 Thread.sleep(500); //沉睡 500ms, 让线程打印 5 个数字 thread.stop(); //中断线程 System.out.println("主线程中断线程"); } }
-- 2. 运行结果 :
线程逻辑开始 0 1 2 3 4 主线程中断线程
线程逻辑开始
0
1
2
3
4
主线程中断线程
-- 3. 总结分析 : 线程直接中断了, 线程中 run() 方法的最后一行代码也没有执行, 循环逻辑结束也没有执行, 说明线程很暴力的直接退出, 没有任何处理;
(2) stop 方法停止线程 捕获 ThreadDeath 异常
关于异常捕捉 :
-- 1. 捕捉 ThreadDeath 异常 : 线程捕获异常处理后, 还会继续执行 try catch 代码块下面的代码;
-- 2. 不捕捉 ThreadDeath 异常 : 线程直接从 stop 时刻退出, 不会执行下面的代码;
stop() 停止线程 并 捕获异常 效果演示 :
-- 1. 代码示例 : 代码中比上面多了一个 catch ThreadDeath 异常的代码块, 其它一样;
public class StopDemo { public static class MyThread extends Thread{ @Override public void run() { try { System.out.println("线程逻辑开始"); super.run(); for(int i = 0; i < 5000; i ++){ System.out.println(i); sleep(100); } System.out.println("线程逻辑结束"); } catch (InterruptedException e) { System.out.println("捕获到了 InterruptedException 异常 , 进入了 catch 代码块"); e.printStackTrace(); }catch (ThreadDeath e){ System.out.println("捕获到了 ThreadDeath 异常 , 进入了 catch 代码块"); e.printStackTrace(); }//catch代码块 System.out.println("run 方法结束"); }//run方法 }//线程 public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(); //新建线程 thread.start(); //线程启动 Thread.sleep(500); //沉睡 500ms, 让线程打印 5 个数字 thread.stop(); //中断线程 System.out.println("主线程中断线程"); } }
-- 2. 运行结果 :
线程逻辑开始 0 1 2 3 4 主线程中断线程 捕获到了 ThreadDeath 异常 , 进入了 catch 代码块 run 方法结束 java.lang.ThreadDeath at java.lang.Thread.stop(Unknown Source) at com.hanshuliang.thread.StopDemo.main(StopDemo.java:31)
-- 3. 总结分析 : 如果捕获了 ThreadDeath 异常, 就会处理这个异常, 并会执行异常处理后面的代码, run() 方法的最后一行代码也执行完毕了;