多线程之线程的创建中断等待 - javaee
创始人
2025-05-31 09:23:32
0

前言

本篇介绍有关线程的创建,中断,等待,描述线程状态等操作,如有错误,请在评论区指正,让我们一起交流,共同进步!


文章目录

  • 前言
    • 1. 创建线程
    • 2. 中断线程
    • 3. 等待线程 - join()
    • 4. 线程状态
  • 总结

本文开始

1. 创建线程

认识多线程代码:

在这里插入图片描述

1.1 创建线程的方式
① 继承Thread类

    static class MyThread extends Thread{@Overridepublic void run() {System.out.println("子线程中 run");}}public static void main(String[] args) {Thread t = new MyThread();//启动线程t.start();}

认识 start 与 run
start: 系统中创建一个新的线程,新的线程再执行run方法 =》有线程的创建
run: 表示线程的入口方法 =》没有创建一个新的线程,而是在主线程中调用run方法;

② 实现Runnable接口

 static class MyThread2 implements Runnable {@Overridepublic void run() {System.out.println("子线程中的 run");}}public static void main(String[] args) {MyThread2 thread2 = new MyThread2();Thread t = new Thread(thread2);t.start();}

③ 匿名内部类实现Thread

 public static void main(String[] args) {Thread t = new Thread() {@Overridepublic void run() {System.out.println("子线程中的 run");}};t.start();}

④ 匿名内部类实现Runnable接口

    public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("子线程中的 run");}});t.start();}

⑤ lambda 表达式实现 =》 推荐使用

  public static void main(String[] args) {Thread t = new Thread( () -> {System.out.println("子线程中的语句");});t.start();}

2. 中断线程

中断线程:使一个线程停止,就是让线程的入口方法run停止(return等操作);

方式1:定义类变量,在主线程中修改类变量让子线程中断(循环中断,线程结束)
执行过程: 下列两个线程(主线程和新创建的线程),重t.start()开始分头执行,新线程执行判断"isQuit" 类变量的真假,为假进入循环执行,与此同时主线程会先执行睡眠代码,执行完毕后再执行修改类变量的操作,此时新线程如果再次判断 “isQuit” 为true 循环条件非真,就会中断循环,结束新线程;

循环判断条件为什么不是定义在类内的局部变量?
lambda表达式访问的限制 =》lambda访问的变量必须是final修饰的变量,或者是在代码中没有改变过的变量;

[注]:lambda表达式可以访问外面的局部变量(变量捕获)
变量捕获的变量必须是“final”修饰的 或者 没有final修饰但代码中没有修改过的变量;

public static boolean isQuit = false;public static void main(String[] args) {Thread t = new Thread( () -> {while (!isQuit) {System.out.println("子线程的语句");//睡眠,防止线程太快,看不清执行过程try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}//修改变量,让子线程终止isQuit = true;}

方式2: 使用Thread的方法 interrupt
【注】Thread类中内置了一个标志位,方便实现代码,标志位默认为假;

创建的新线程获取标志位使用Thread中的方法:Thread.currentThread().isInterrupted(); => 判断当前线程的中断标志位
currentThread(): 获取当前线程的实例对象
isInterrupted(): 返回当前线程的状态(true或者false)

执行过程:下列两个线程(主线程和新创建的线程),重t.start()开始分头执行,主线程执行到interrupt(), 使用interrupt将获取到的标志位并改为true,此时创建的线程t, 在执行循环的时候,循环条件判断 !true 新线程就会中断;
interrupt 方法的作用:
① 设置标志为 true;
② 线程正在阻塞状态,此时会把阻塞状态(产生阻塞状态像sleep,wait等)唤醒,通过抛出异常的方式让sleep(阻塞状态) 立即结束;
③ 使用interrupt()方法不会让线程立即结束,只是让线程知道自己该结束了,这些代码控制是灵活的;

【注】sleep被唤醒,此时sleep会自动把isInterrupted的标志位清空(true =》false)就是更改标志位状态;=》sleep被唤醒做的两个事情:抛出异常 + 清空标志位

   public static void main(String[] args) {Thread t = new Thread( () -> {while (Thread.currentThread().isInterrupted()) {System.out.println("子线程的语句");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();break; // 为了让循环结束设置break;//不设置break,抛完异常循环还会执行,并不会结束}}});t.start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}//interrupt(): 用来设置标志位t.interrupt();}

3. 等待线程 - join()

1.为什么需要线程等待呢?
线程之间是并发执行的,线程之间的调度是无序的,随机的,让多个线程执行的先后顺序无法确定;

由此就可以使用 join()方法来解决
2.join() 等待方法两种:
①join():无参一直等待
②join(最大等待的时间):等待最长时间自己可以指定

等待执行过程:
有线程A,B,在线程B中调用join()方法,会让B线程等待,A线程执行结束后,再执行A线程;=》那个线程中调用join()方法,那个线程就等待别的线程,等别的线程执行结束后再执行调用等待的那个线程;
例如:
在主线程中调用t.join() 会阻塞主线程(让主线程等待),等新线程执行结束,主线程才会继续向下执行;

如下代码:如果线程等待,结果一定是先打印"run 中的打印", 在打印"主线程中的main";如果没有线程等待,两者顺序就不确定;

public static void main(String[] args) throws InterruptedException {Thread t = new Thread( () -> {System.out.println("run 中的打印");});t.start();//主线程中执行的代码t.join();//线程等待System.out.println("主线程中的main");}

4. 线程状态

线程的6种状态:
① New :系统中线程还没有创建出来,只有Thread对象
② RUNNABLE:就绪状态;(正在CPU运行的状态或者准备在CPU上运行的状态)
③ TERMINATED(terminated):线程结束状态,Thread对象还存在
④ TIMED_WAITING(timed_waiting):时间等待状态;(sleep方法等)
⑤ BlOCKED: 等待锁出现状态;
⑥ WAITING:使用wait方法出现的状态

在这里插入图片描述


总结

✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...