【JavaEE多线程】理解和管理线程生命周期

目录

    • Thread
      • Thread类的常用构造方法
      • Thread类的常见属性
      • 启动一个线程-start()
      • 终止一个线程
      • 等待一个线程-join()
      • 线程的状态


Thread

Thread 就是在 Java 中,线程的代言人。系统中的一个线程,就对应到 Java 中的一个 Thread 对象。围绕线程的各种操作,都是通过 Thread 来展开的

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联

用我们上面的例子来看,每个执行流,也需要有一个对象来描述,类似下图所示,而 Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

在这里插入图片描述

Thread类的常用构造方法

方法说明
Thread()创建线程对象
Thread(Runnable target)使用 Runnable 对象创建线程对象
Thread(String name)创建线程对象,并命名
Thread(Runnable target, Strin name)使用 Runnable 对象创建线程对象,并命名
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");```

Thread类的常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  1. ID(getId):线程的身份表示(在JVM这里给线程设定的身份标识),一个线程可以有多个身份标识

  2. 名称(getName):各种调试工具用到

  3. 状态(getState):Java中的线程状态和操作系统中有一定差异

  4. 优先级(getPriority):设置/获取线程优先级作用不是很大,线程的调度主要还是系统内核来负责的,系统调度的速度实在太快

  5. 是否后台线程(isDaemon)

    • 后台线程/守护线程:不太影响进程结束

    • 前台线程:会影响进程结束,如果前台线程没执行完,进程是不会结束的

    • 一个进程中所有的前台线程都执行完,退出了,此时即使存在后台线程仍然没执行完也会随着进程一起退出

    • 影响进程退出的就是前台,不影响的就是后台

    • 创建的线程默认是前台线程,通过setDaemon显式的设置成后台

  6. 是否存活(isAlive):Thread对象,对应的线程(系统内核中)是否存活。

    • Thread对象的生命周期,并不是和系统中的线程完全一致的
  7. 是否被中断(isInterrupted):看下面

启动一个线程-start()

  1. start方法,在系统中真正创建出线程
    1. 创建出PCB
    2. 把PCB加入到对应链表
  2. 操作系统内核=内核+配套的程序
  3. 内核:一个系统最核心的功能
    1. 对下,管理好各种硬件设备
    2. 对上,给各种程序提供稳定的运行环境
  4. start方法本身执行成功是一瞬间的,只是告诉系统你要创建一个线程,调用完start后,代码就会立即继续执行start后续的逻辑

终止一个线程

  1. 一个线程的run方法执行完毕,就算终止了

  2. 此处的终止线程,就是想办法让run方法能够尽快执行完毕

  3. 方法:

    1. 程序员手动设定标志位,通过这个来让run尽快结束
    private static class MyRunnable implements Runnable {public volatile boolean isQuit = false;@Overridepublic void run() {while (!isQuit) {System.out.println(Thread.currentThread().getName()+ ": 别管我,我忙着转账呢!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+ ": 啊!险些误了大事");}
    }public static void main(String[] args) throws InterruptedException {MyRunnable target = new MyRunnable();Thread thread = new Thread(target, "李四");System.out.println(Thread.currentThread().getName()+ ": 让李四开始转账。");thread.start();Thread.sleep(10 * 1000);System.out.println(Thread.currentThread().getName()+ ": 老板来电话了,得赶紧通知李四对方是个骗子!");target.isQuit = true;
    }
    
    1. 直接Thread类,给我们提供好了现成的标志位,不用手动设置标志位
    private static class MyRunnable implements Runnable {@Overridepublic void run() {// 两种方法均可以while (!Thread.interrupted()) {//while (!Thread.currentThread().isInterrupted()) {System.out.println(Thread.currentThread().getName()+ ": 别管我,我忙着转账呢!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();System.out.println(Thread.currentThread().getName()+ ": 有内鬼,终止交易!");// 注意此处的 breakbreak;}}System.out.println(Thread.currentThread().getName()+ ": 啊!险些误了大事");}
    }public static void main(String[] args) throws InterruptedException {MyRunnable target = new MyRunnable();Thread thread = new Thread(target, "李四");System.out.println(Thread.currentThread().getName()+ ": 让李四开始转账。");thread.start();Thread.sleep(10 * 1000);System.out.println(Thread.currentThread().getName()+ ": 老板来电话了,得赶紧通知李四对方是个骗子!");thread.interrupt();
    }
    
  4. 当sleep被唤醒以后,程序员可以有以下几种操作方式:

    1. 立即停止循环,立即结束线程(直接break)
    2. 继续做点别的事情,过一会儿再结束线程(catch中执行别的逻辑,执行完再break)
    3. 忽略终止的请求,继续循环(不写break)
  5. thread 收到通知的方式有两种:

    1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志
      • 当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程
    2. 否则,只是内部的一个中断标志被设置,thread 可以通过
      • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
      • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志

等待一个线程-join()

  1. 多个线程是并发执行的。具体的执行过程都是由操作系统负责调度的。操作系统的调度线程的过程,是“随机”的。无法确定线程执行的先后顺序
  2. 等待线程,就是一种规划 线程结束 顺序的手段
  3. 注意:join()方法也会抛出Interrupted异常
  4. 谁调用join方法,谁就强占cpu资源,直至执行结束
  5. A B两个线程,希望B先结束A后结束,此时就可以让A线程中调用B.join()的方法。此时,B线程还没执行完,A线程就会进入"阻塞"状态。就相当于给B留下了执行的时间。B执行完毕之后,A再从阻塞状态中恢复回来,并且继续往后执行。如果A执行到B.join()的时候,B已经执行完了,A就不必阻塞了,直接往下执行就可以了
  6. 阻塞:让代码暂时不继续执行了(该线程暂时不去CPU上参与调度)
  7. sleep也能让线程阻塞,阻塞是有时间限制的
  8. join的阻塞,则是“死等”“不见不散”
  9. sleep、join、wait…产生阻塞之后,都是可能被interrupt方法唤醒的,这几个方法都会在被唤醒之后自动清除标志位(和sleep类似),这些方法都会抛出Interrupted异常

线程的状态

  • 先谈谈进程里PCB里的状态字段:就绪阻塞状态(这些是系统设定的状态,Java又把这些细分了)
  • 以下则是线程的状态:
  1. NEW**(开始前)**: 安排了工作, 还未开始行动 (Thread对象创建好了,但还没有调用start()方法)

  2. RUNNABLE**(就绪状态): 可工作的. 又可以分成正在工作中即将开始工作**

    1. 线程正在CPU上运行

    2. 线程正在排队,随时可以去CPU运行

  3. BLOCKED**(阻塞状态)**: 这几个都表示排队等着其他事情 :因为锁

  4. WAITING**(阻塞状态)**: 这几个都表示排队等着其他事情 :因为调用了wait

  5. TIMED_WAITING**(阻塞状态)**: 这几个都表示排队等着其他事情 :因为调用了sleep

  6. TERMINATED**(结束后)**: 工作完成了

  • 线程状态转换图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/816674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 设计模式系列:模板方法模式

简介 模板方法模式是一种行为型设计模式,它定义一个操作中的算法骨架,将一些步骤推迟到子类中。模板方法模式使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。 在模板方法模式中,抽象类中定义了一系列基本操…

申请OV SSL证书的好处

什么是OV SSL证书: OV SSL证书也叫组织验证型SSL证书,是众多SSL证书当中最受广大用户欢迎的一种类型。因为它不仅需要验证域名的所有权,还需要对企业的相关身份信息进行审核,确保企业是一个真实存在的合法实体。除了这些&#xf…

Rust取代C++? 保守了!关于未来的讨论

当各种平台在大肆讨论rust即将取代C/C的时候,已经有不少人意识到这种讨论是聒噪而无聊的。笔者和老师们通过周末茶会的讨论,认为现今世界常见的大多数编程语言都会在50-80年内被AI取代,同时供人类审计而诞生的“审计语言”会兴起。届时计算机…

Beego 使用教程 1:项目创建

beego 是一个用于Go编程语言的开源、高性能的 web 框架 beego 被用于在Go语言中企业应用程序的快速开发,包括RESTful API、web应用程序和后端服务。它的灵感来源于Tornado, Sinatra 和 Flask beego 官网:http://beego.gocn.vip/ 上面的 beego 官网如果访问不到,看这篇文章…

华为机考入门python3--(15)牛客15-求int型正整数在内存中存储时1的个数

分类:二进制 知识点: int转二进制 binary bin(n)[2:] 题目来自【牛客】 def count_ones_in_binary(n): # 将输入的整数转换为二进制字符串 # bin(n)为0b11011binary bin(n)[2:]# 初始化计数器为0 count 0 # 遍历二进制字符串的每一位 fo…

YOLOv9/YOLOv8算法改进【NO.117】 使用Wasserstein Distance Loss改进小目标的检测效果

前 言 YOLO算法改进系列出到这,很多朋友问改进如何选择是最佳的,下面我就根据个人多年的写作发文章以及指导发文章的经验来看,按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通: 首推…

多线程(51)忙等待

忙等待(Busy-waiting)是一种同步机制,其中一个进程或线程重复检查某个条件是否满足以便继续执行,而不是进入休眠或阻塞状态。这个条件通常与某种资源或锁的可用性有关。忙等待常常与自旋锁相关联,因为自旋锁就是通过忙…

StarUML笔记之从UML图生成C++代码

StarUML笔记之从UML图生成C代码 —— 2024-04-14 文章目录 StarUML笔记之从UML图生成C代码1.Add Diagram2.在TOOLBOX中左键点击Class,松开,然后在中间画面再左键点击,即可出现UML3.修改类图,并添加接口,方法,属性,我…

webpack-(plugin,本地服务器,路径别名,安装vue)

安装vue npm i vue-loader -D npm i vue 编写一个vue文件: 在index.html中设置 一个id为app的div 将vue文件挂载到app中 vue比较特殊,除了使用loader外,还使用了plugin const path require("path"); const { VueLoaderPlugin …

数据库-Redis(11)

目录 51.什么是Redis事务? 52.Redis事务相关命令? 53.Redis事务的三个阶段?

将图片数据转换为张量(Go并发处理)

在Go语言中,将图片数据转换成Tensor通常需要依赖一些外部库,编写一个简单的程序,该程序批量同时处理图片,将其转换为对应的浮点数张量。 假设图片是单通道(灰度图)或者三通道(彩色图&#xff0…

论文笔记:SmartPlay : A Benchmark for LLMs as Intelligent Agents

iclr 2024 reviewer评分 5688 引入了 SmartPlay,一种从 6 种不同游戏中提取的基准 衡量LLM作为智能体的能力 1 智能代理所需的能力 论文借鉴游戏设计的概念,确定了智能LLM代理的九项关键能力,并为每项能力确定了多个等级: 长文…

Unity WebGL 2022 Release-Notes

🌈WebGL 2022 Release-Notes 版本更新内容2022.3.16WebGL: Fixed a bug that causes a parsing error due to misplaced regex.(UUM-21896)2022.3.15WebGL: Fixed a bug that caused for input to not be released when focus was removed from canvas on Windows C…

一个基于单片机内存管理-开源模块

概述 此模块是一位大佬写的应用于单片机内存管理模块mem_malloc,这个mem_malloc的使用不会产生内存碎片,可以高效利用单片机ram空间。 源码仓库:GitHub - chenqy2018/mem_malloc mem_malloc介绍 一般单片机的内存都比较小,而且没有MMU,malloc 与free的使用容易造成内存碎…

27、滑动窗口

滑动窗口 题目描述 给定一个大小为 n ≤ 1 0 6 n≤10^6 n≤106 的数组。 有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。 您只能在窗口中看到k个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子: 该数组为[1 3 -1 -3 5 3 6 7]…

《由浅入深学习SAP财务》:第2章 总账模块 - 2.7 总账模块报表 -2.7.2 对外报表:现金流量表

2.7.2 对外报表:现金流量表 现金流量表包括直接法和间接法。使用SAP出具现金流量表,一般只能出具直接法报表。间接法是指按照净利润倒推出现金流量的发生额,由于其中存在人为“分析”的因素,很难直接通过科目的加加减减得出所需要…

神经网络模型底层原理与实现10-softmax的实现

import torch from IPython import display from d2l import torch as d2l batch_size256 #定义训练和验证数据集 train_iter,test_iterd2l.load_data_fashion_mnist(batch_size) #参数初始化,把输入图片看成长度784的向量,这个数据集有十个类别,输出为1…

小蚕爬树问题

小蚕爬树问题 问题描述: 编写一个函数 int day(int k,int m,int n),其功能是:返回小蚕需要多少天才能爬到树顶(树高 k 厘米,小蚕每天白天向上爬 m 厘米,每天晚上下滑 n 厘米,爬到树顶后不再下滑&#xff0…

(六)C++自制植物大战僵尸游戏关卡数据讲解

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/xjvbb 游戏关卡数据文件定义了游戏中每一个关卡的数据,包括游戏类型、关卡通关奖励的金币数量、僵尸出现的波数、每一波出现僵尸数量、每一波僵尸出现的类型等。根据不同的游戏类型,定义了不同的通…

kafka ----修改log4j、jmx、jvm参数等

1、修改log4j 日志路径 在kafka-run-class.sh文件中修改如下配置,将 LOG_DIR变量指定为自己想要存储的路径 # Log directory to use if [ "x$LOG_DIR" "x" ]; thenLOG_DIR"$base_dir/logs" fi2、修改jmx参数 在kafka-run-class.s…