一. 线程启动

线程启动 :

-- 1. 继承 Thread 运行线程 : 重写 Thread 类的 run 方法, 然后执行该线程;

-- 2. 实现 Runnable 接口, 并运行线程;

-- 代码示例 :

package com.hanshuliang.thread;public class ThreadStart {public static void main(String[] args) {//1. 继承 Thread 运行线程MyThread thread = new MyThread();thread.start();//2. 实现 Runnable 接口, 并运行线程Thread runnableThread = new Thread(new MyRunnable());runnableThread.start();}//1. 继承 Thread 类static class MyThread extends Thread{@Overridepublic void run() {super.run();System.out.println("MyThread 线程启动");}}//2. 实现 Runnable 接口static class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("MyRunnable 线程启动");}}
}

-- 运行结果 :

MyThread 线程启动
MyRunnable 线程启动

三. 线程停止

线程停止常用方法 :

-- 1. 使用 interrupt() 方法停止线程;

-- 2. 使用退出标志, 让线程正常退出;

-- 3. 弃用的方法 (不推荐) : 使用 stop() 方法强制停止线程, 但是该方法已经作废, 不建议使用;

1. 使用 interrupt() 方法停止线程


(1) 线程无法立即停止

interrupt() 使用说明 :

-- 打标记 : 调用该方法, 不能马上停止该线程, 只是在当前线程打了一个停止标记;

代码示例 :

-- 代码 :

public class InterruptDemo {public static class MyThread extends Thread {@Overridepublic void run() {super.run();for (int i = 1; i <= 1000000; i++)  //打印 一百万 数字, 大概持续 5 ~ 10 秒左右System.out.println(i);}}public static void main(String[] args) throws InterruptedException {MyThread thread = new MyThread();thread.start();                       //启动线程Thread.sleep(100);                    //启动线程 100ms 后中断线程thread.interrupt();                   //中断线程}
}

-- 运行结果 : 这里只贴上最后几行 命令行的运行结果;

... ...
999996
999997
999998
999999
1000000

-- 总结 : 在上述程序中, 打印了 100 万数字, 从 1 到 100 0000, 整个过程持续了 10秒左右, 但是我们在 线程开始后 100ms 就中断了线程, 但是线程还是执行完毕了, 说明线程并没有在调用 interrupt() 方法后立即停止;

(2) 线程停止状态判定

两个线程停止状态判定的方法 :

-- 1. interrupted() 方法 : ①判断当前线程的中断标志, ②如果是中断标志 true, 那么清除中断标志, 改为 false;,③ 连续两次调用该方法, 第二次返回 false, ④ 静态方法 : 该方法是测试当前线程的中断标志, 在哪个线程中调用, 就是判定的哪个线程的中断标志, 不管调用的主体是哪个线程;

-- 2. isInterrupted() 方法 : 判断线程的 中断状态, 不管真实的运行状态, 只关心状态;

-- 注意 : 两个方法都是判断 中断状态的, 与线程的真实运行状况无关;

(3) interrupted() 方法测试

interrupted () 方法测试1 : 测试 interrupted 方法的判断是否已经中断的效果;

-- 测试代码 :

public class InterruptedDemo1 {public static class MyThread extends Thread {@Overridepublic void run() {super.run();for (int i = 1; i <= 10; i++)    //打印10个数字System.out.println(i);}}public static void main(String[] args) throws InterruptedException {MyThread thread = new MyThread();thread.start();                      //启动线程thread.interrupt();                   //启动线程后马上 中断线程System.out.println("第一次 : thread.interrupted() = " + thread.interrupted());System.out.println("第二次 : thread.interrupted() = " + thread.interrupted());}
}

-- 执行结果 :

第一次 : thread.interrupted() = false
1
2
第二次 : thread.interrupted() = false
3
4
5
6
7
8
9
10

-- 总结 : 启动线程后, 立即调用 interrupt 方法 中断线程, 但是 在主线程中 调用 thread.Interrupted() 方法, 打印出来的是 主线程的中断状态标志, 虽然是调用的 thread 子线程的对象的方法, 但是该方法是一个静态方法, 在哪个线程调用, 就是打印哪个线程的中断标志;

interrupted () 方法测试2 : 测试 interrupted 方法的 清除 中断状态 的效果;

-- 1. 测试代码 :

public class InterruptedDemo {public static void main(String[] args) throws InterruptedException {Thread.currentThread().interrupt();    //中断主线程System.out.println("第一次 : thread.interrupted() = " + Thread.interrupted());System.out.println("第二次 : thread.interrupted() = " + Thread.interrupted());}
}

-- 2. 执行结果 :

第一次 : thread.interrupted() = true
第二次 : thread.interrupted() = false

-- 3. 总结 : 使用 interrupted() 方法, 如果当前线程的状态是中断状态, 即返回了 true, 那么需要清除该标志, 下一次调用 interrupted() 方法后, 返回值就是 false 了;

(4) isInterrupted() 方法测试

isInterrupted() 方法测试1 : 测试其 中断状态, 与上面的 interrupted() 方法对比;

-- 1. 测试代码 :

public class IsInterruptedDemo {public static class MyThread extends Thread {@Overridepublic void run() {super.run();for (int i = 1; i <= 10; i++)   //打印10个数字System.out.println(i);}}public static void main(String[] args) throws InterruptedException {MyThread thread = new MyThread();thread.start();                      //启动线程thread.interrupt();                   //启动线程后马上 中断线程System.out.println("第一次 : thread.interrupted() = " + thread.isInterrupted());System.out.println("第二次 : thread.interrupted() = " + thread.isInterrupted());}
}

-- 2. 返回值 :

第一次 : thread.interrupted() = true
1
2
第二次 : thread.interrupted() = true
3
4
5
6
7
8
9
10

-- 3. 总结分析 : isInterrupted() 方法 只 判断 被调用对象的 该对象线程的 线程的中断 状态, 不管线程的真实运行状况, 即使当前线程正在运行, 但是线程调用了 interrupt() 方法, 其中断状态为 true, 因此 isInterrupted() 方法的返回值一直是 true;

-- 4. 对比 interrupted() 方法 : interrupted() 方法反应的是真实的线程运行状态, 线程正在运行, 那么返回 false, 如果线程没有运行, 返回 true;

-- 5. 对比 Interrupted() 方法 (静态与普通方法) : isInterrupted 方法是非静态方法, 哪个对象调用返回的就是哪个对象的中断状态; interrupted 是静态方法, 在哪个线程调用就是返回哪个线程的中断状态;

2. 异常法停止线程


(1) 线程循环中正常退出停止

退出方法 : 正常退出线程;

-- 1. 前提 : 线程中执行一个循环;

-- 2. 中断线程 : 执行线程中断操作, 调用 线程的 interrupt() 方法;

-- 3. 查询中断标志 : 在线程中通过调用 interrupted 方法, 查询当前的线程中断标志, 之后该方法就会将中断标志清除;

-- 4. 退出循环 : 如果查询到中断标志后, 直接使用 break 退出循环;

-- 5. 弊端 : 在线程中, 线程没有真正的停止, 线程还是完整的执行了;

线程正常退出代码示例 :

-- 1. 代码 :

public class ExceptionInterruptDeo {public static class MyThread extends Thread{@Overridepublic void run() {super.run();for(int i = 0; i < 500; i ++){if(interrupted()){              //判断线程的中断状态, 如果中断直接 breakSystem.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 {@Overridepublic void run() {try {super.run();for (int i = 0; i < 500; i++) {if (interrupted()) { // 判断线程的中断状态, 如果中断直接 breakSystem.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.InterruptedExceptionat 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{@Overridepublic void run() {try {System.out.println("线程逻辑开始");super.run();sleep(1000);   //启动后立即进入沉睡状态, 沉睡 1000msSystem.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 interruptedat 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{@Overridepublic void run() {try {System.out.println("线程逻辑开始");super.run();for(int i = 0; i < 500; i ++)System.out.println(i);sleep(1000);  //启动后立即进入沉睡状态, 沉睡 1000msSystem.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 interruptedat 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{@Overridepublic 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
主线程中断线程

-- 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{@Overridepublic 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.ThreadDeathat java.lang.Thread.stop(Unknown Source)at com.hanshuliang.thread.StopDemo.main(StopDemo.java:31)

-- 3. 总结分析 : 如果捕获了 ThreadDeath 异常, 就会处理这个异常, 并会执行异常处理后面的代码, run() 方法的最后一行代码也执行完毕了;

5. return 停止线程

return 停止线程说明 :

-- 1. 执行过程 : 线程运行中, 随时监测中断标记, 如果检测到中断标记后, 直接 return 退出 run 方法;

-- 2. 不建议使用该方法, 多个 return 会污染代码;

return 退出演示 :

-- 1. 代码示例 :

public class ReturnDemo {public static class MyThread extends Thread{@Overridepublic void run() {super.run();for(int i = 0; i < 500; i ++){if(interrupted()){             //判断线程的中断状态, 如果中断直接 breakSystem.out.println("停止状态, return 退出");return;}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. 执行结果 :

... ...
35
36
37
38
39
主线程执行完毕
停止状态, return 退出

-- 3. 总结分析 : 使用 return 直接退出 run 方法, 确实实现了立即停止线程的目的, 但是我们还是建议使用 异常法 控制线程停止;

.

四. 线程暂停

线程停止常用方法 :

-- 1. 使用 interrupt() 方法停止线程;

-- 2. 使用退出标志, 让线程正常退出;

-- 3. 弃用的方法 (不推荐) : 使用 stop() 方法强制停止线程, 但是该方法已经作废, 不建议使用;

1. 使用 interrupt() 方法停止线程


(1) 线程无法立即停止

interrupt() 使用说明 :

.

.

.

.

转载注明出处 : http://blog.csdn.net/shulianghan/article/details/52369486

【Java 语言】Java 多线程 一 ( 线程基础 : 线程启动 | 线程停止 | 线程暂停 | 线程优先级 | 守护线程)相关推荐

  1. java语言基础 : 初识计算机和Java语言-----java初识之路

    初识计算机和Java语言 第一节:计算机的体系结构(常识) 1.计算机的基本概念 计算机(Computer)俗称电脑,是一种用于高级计算,使用非常广泛的设备,主要由 计算机硬件和 计算机软件两个部分组 ...

  2. Java语言程序设计与数据结构(基础篇)梁勇第二章书中例题

    程序清单2-1:ComputeArea.java public class ComputeArea {public static void main(String[] args) {// TODO A ...

  3. 《Java语言程序设计与数据结构(基础篇)》第11版第四章复习题答案

    4.2.1答案:a: 2.0  b: 0.0  c: 1.0  d: 4.0  e: 1.0  f: 2.718281828459045  g: 3  h: -2.0 i: -2.0  j: -3.0 ...

  4. Java植物名录程序_程序员用Java语言编写多线程应用程序,程序员能控制的关键性工作有两个方面:一是编写线程的_________方法;二是建立线程实例。...

    沟通的目的是打造"3G团队",其中的"3G"具体指: "啊,时间过得真快啊!"中的"啊" 活塞与气缸盖.气缸壁共同组成燃 ...

  5. java多线程实现卖火车票小案例同步代码块优先级守护线程

    /***  *   * @author 时光机jay  * @version 1.8  * @since 2020/9/28  *   * */ public class Test33 {     s ...

  6. Java语言程序设计与数据结构(基础篇)梁勇第一章书中例题

    程序清单1-1:Welcome.java public class Welcome {public static void main(String[] args) {System.out.printl ...

  7. Java语言程序设计与数据结构(基础篇)梁勇第九章 *9.3

    *9.3(使用Data类)编写程序创建一个Data对象,设置它的流逝时间分别为10000.100000.1000000.10000000.100000000.1000000000.1000000000 ...

  8. 创造与魔法java语言_创造与魔法基础魔法大全 超实用基础魔法推荐

    魔法是创造与魔法游戏中的一个玩法,可以利用魔法来实现一些特殊的效果,下面一起来看一下基础魔法推荐吧. 本文作者:大不点 魔法怎么画?有什么用?怎么用?今天,就来教教大家,创造与魔法的魔法使用方法,首先 ...

  9. 猎豹怎么运行java_猎豹网校 数据结构与算法 Java语言 JAVA语言视频教程(火评)...

    01.NetBeans_下载和安装.mp4  02.JavaDS_数据结构和算法的概述.mp4 03.JavaDS_数组基础知识.mp4 04.JavaDS_有序数组和二分查找.mp4 05.Java ...

最新文章

  1. (2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第八题包子凑数)
  2. HBase–常用API操作篇
  3. ext js IE9显示白板 页面浏览器模式强制渲染IE8
  4. python测验2_python接口测试(二)
  5. 图中长度为k的路径的计数
  6. nodejs-EventEmitter
  7. 软件需求分析报告模板_管理费用财务分析怎么做,拿走这个分析模板写进你的报告吧...
  8. Hadoop Name node is in safe mode报错解决办法
  9. 删除list中的一个节点
  10. 综述 | Google-斯坦福发布~深度学习统计力学
  11. mysql 查询列表是否关注_点赞功能,用mysql还是redis?
  12. 菜鸟学习笔记:Java提升篇9(网络1——网络基础、Java网络编程)
  13. 飞龙的安卓逆向系列教程
  14. mysql 全文检索 教程_mysql怎么做全文检索
  15. Atitit.软件开发的几大规则,法则,与原则Principle v5 1.1. 修改历史 2 2. 设计模式六大原则 3 2.1. 设计模式六大原则(1):单一职责原则 3 2.2. 设计模式六
  16. 分享80个贺卡图片PHP源码,总有一款适合你
  17. Debug无忧!清华校友打造Python调试神器!
  18. 仿《广州从化区慢性病地理信息平台》项目研发总结
  19. C语言中内嵌汇编asm语法
  20. Mac系统关闭重启电脑后「重新打开应用及其窗口」功能的方法

热门文章

  1. Qt 2D绘图之二:抗锯齿渲染和坐标系统
  2. [转]MySQL Explain详解
  3. Java学习---RMI 技术分析[Hessian]
  4. 小x的质数(线性O(n)筛素数)
  5. Mysql存储引擎MyIsAM和InnoDB区别
  6. 2014百度之星资格赛 1001:Energy Conversion(水题,逻辑题)
  7. Ubuntu下查看命令的源码
  8. 杭电多校(三)2019.7.29--暑假集训
  9. selenium中的对文本进行全选,复制,粘贴,剪切和删除的操作
  10. css中那些容易被我们程序猿所忽略的选择器