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

简介: 【Java 语言】Java 多线程 一 ( 线程基础 : 线程启动 | 线程停止 | 线程暂停 | 线程优先级 | 守护线程)(二)

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() 方法的最后一行代码也执行完毕了;



目录
相关文章
|
2月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
102 4
|
2月前
|
Java
Java语言实现字母大小写转换的方法
Java提供了多种灵活的方法来处理字符串中的字母大小写转换。根据具体需求,可以选择适合的方法来实现。在大多数情况下,使用 String类或 Character类的方法已经足够。但是,在需要更复杂的逻辑或处理非常规字符集时,可以通过字符流或手动遍历字符串来实现更精细的控制。
230 18
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
160 1
|
2月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
176 1
|
3月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
144 0
|
3月前
|
存储 Java Apache
Java语言操作INI配置文件策略
以上步骤展示了基本策略,在实际项目中可能需要根据具体需求进行调整优化。例如,在多线程环境中操作同一份配置时需要考虑线程安全问题;大型项目可能还需考虑性能问题等等。
172 15
|
3月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
231 16
|
4月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
4月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践

热门文章

最新文章