当前位置: 首页 > news >正文

【JAVAEE】多线程

【JAVAEE】多线程

  • 一、进程
      • 1.1 进程的定义
      • 1.2 进程和线程的联系
  • 二、线程
      • 2.1 JConsole工具
      • 2.2 创建线程
        • 2.2.1 Thread类,start(),run()
        • 2.2.2 继承Thread类
        • 2.2.3 实现Runnable接口
        • 2.2.4 匿名内部类
        • 2.2.5 使用Runnable接口的匿名内部类
        • 2.2.6 使用lambda表达式
      • 2.3 Thread类及常用方法
        • 2.3.1 Thread类的构造方法
        • 2.3.2 Thread类的常见属性
      • 2.4 线程状态
      • 2.5 后台线程和前台线程
      • 2.6 休眠线程
      • 2.7 线程等待
      • 2.8 终止线程
        • 2.8.1 自定义标志位终止线程
        • 2.8.2 使用自带标志位终止线程

博客结尾包含此篇博客的全部代码!!!

一、进程

1.1 进程的定义

  • 进程(Process)是计算机操作系统中的一个核心概念,它是程序在计算机上的一次动态执行实例。换句话说,进程是程序运行时的活动表现形式。它包含了程序代码、数据、运行状态以及系统资源的分配情况。进程相当于一个正在运行的程序
  • 进程也是系统分配资源的基本单位

在这里插入图片描述

1.2 进程和线程的联系

首先,并发编程成为我们的需求!每个客户端给服务器发送请求,服务器就需要给客户端提供服务。在90年代,多进程是一种解决方案!!!

那么既然有解决方法,为什么还要引入线程?
线程:线程是轻量级的进程!!!

线程相比于进程:

  • 创建线程比创建进程更快。
  • 销毁线程比销毁进程更快。
  • 调度线程比调度进程更快。

举个例子:

假设这个任务是“消灭”桌子上的两只鸡,在一个房间中有一个桌子,桌子上放了两只鸡。
进程的解决方法:再创建一个房间,将这两只鸡分开,分别“消灭”。
在这里插入图片描述
线程的解决方法:在这个房间中“消灭”这两只鸡。
在这里插入图片描述
这两个对比你发现:相同的人数,进程需要再创建一个房间(开销很大),而线程则啥都不需要添加。

二、线程

2.1 JConsole工具

在创建线程之前,先给大家介绍一下JConsole 工具, JConsole是JDK 自带的一款图形化监控和管理工具,基于 JMX(Java Management Extensions)技术实现。它能够连接到本地或远程的 Java 虚拟机(JVM),并实时监控和管理 Java 应用程序的性能和资源使用情况。
这里我们就用它来监控我们的线程!
JConsole:找到我们的JDK安装的安装路径,像我这里安装的JDK17–>bin–>jconsole.exe
在这里插入图片描述
如何使用?
测试代码:代码运行起来才能观察到,如果线程结束就观察不到。

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println(" hello Thread");}}
}public class Demo1 {public static void main(String[] args) {MyThread t1 = new MyThread();t1.start();}
}

在这里插入图片描述

在这里插入图片描述
刚进去出现不安全连接,由于是我是自己练习,所以点不安全连接。
在这里插入图片描述

2.2 创建线程

2.2.1 Thread类,start(),run()
  • Thread类:线程,是操作系统的概念,操作系统定义了一些api(应用程序编程接口)来供程序员使用,而java中将这些api封装成Thread类来供使用!Thread类在java.long这个包中,所以用的时候不需要导包。
  • start():用于启动一个新线程,线程调度器会调用 run() 方法。start() 方法只能被调用一次。如果尝试多次调用 start(),会抛出 IllegalThreadStateException 异常。
  • run():定义线程的执行逻辑,但不会启动新线程。如果需要启动新线程,必须通过 start() 方法。相当于线程的入口。
2.2.2 继承Thread类

代码:

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println(" hello Thread");}}
}public class Demo1 {public static void main(String[] args) {MyThread t1 = new MyThread();t1.start();while(true) {System.out.println(" hello main");}}
}
2.2.3 实现Runnable接口

实现Runnable接口的MyRunnnable类,将new MyRunnable()当作一个对象传给Thread的构造函数。
代码:

class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Hello Thread");}
}public class Demo2 {public static void main(String[] args) {Thread t1 = new Thread(new MyRunnable());t1.start();}
}
2.2.4 匿名内部类
public class Demo3 {public static void main(String[] args) {Thread thread = new Thread(){@Overridepublic void run() {System.out.println("Hello Thread");}};thread.start();System.out.println("Hello main");}
}
2.2.5 使用Runnable接口的匿名内部类
public class Demo4 {public static void main(String[] args) {Thread t1 = new Thread(new Runnable(){@Overridepublic void run() {System.out.println("Hello Thread");}});t1.start();}
}
2.2.6 使用lambda表达式
public class Demo5 {public static void main(String[] args) {Thread thread = new Thread(()->{while(true){System.out.println("Hello Thread");}});thread.start();while(true){System.out.println("Hello main");}}
}

2.3 Thread类及常用方法

2.3.1 Thread类的构造方法

在这里插入图片描述
解释一下第四个Thread(Runnable target,String name)!


public class Demo6 {public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("Hello Thread");}}}, "Thread1");thread.start();while (true) {System.out.println("Hello main");}}
}

在这里插入图片描述

在这里插入图片描述

2.3.2 Thread类的常见属性

在这里插入图片描述
• ID 是线程的唯⼀标识,不同线程不会重复
• 获取线程的名称
• 获取线程的当前状态,如新建、就绪、运行、阻塞、等待、终止等
• 优先级⾼的线程理论上来说更容易被调度到
• 关于后台线程,需要记住⼀点:JVM会在⼀个进程的所有⾮后台线程结束后,才会结束运⾏。
• 是否存活,即简单的理解,为 run ⽅法是否运⾏结束了
• 判断线程是否被中断。线程的中断状态可以通过调用 interrupt() 方法来设置,该方法会改变线程的中断状态,但不会停止线程的执行

2.4 线程状态

public class Demo7 {public static void main(String[] args) {for(Thread.State state: Thread.State.values()) {System.out.println(state);}}
}

获取线程的所有状态:
在这里插入图片描述
• NEW:

  • 当线程对象被创建,但尚未调用 start() 方法时,线程处于新建状态。
  • 在这个状态下,线程尚未开始执行。
public class Demo7 {public static void main(String[] args) {Thread thread=new Thread(()->{System.out.println("Hello Thread");});System.out.println(thread.getState());thread.start();}
}

• RUNNABLE:

  • 当调用线程的 start() 方法后,线程进入就绪状态。
  • 在这个状态下,线程已经准备好运行,等待 CPU 时间片以便执行。
  • 就绪状态的线程可能正在 JVM 中运行,也可能正在等待操作系统调度。
public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{for(int i=0;i<3;i++) {System.out.println("Hello Thread");}});System.out.println(thread.getState());thread.start();System.out.println(thread.getState());}
}

• BLOCKED: 由锁导致的,后面会出一篇关于线程安全问题,到时候会详细介绍,这里就不过多介绍了

  • 当线程等待获取一个排他锁,如同步块或同步方法中的锁时,线程进入阻塞状态。
  • 线程在等待锁释放后才能继续执行。
  • 阻塞状态的线程不会被分配 CPU 时间片。

• WAITING:
时间阻塞(这个等待是没时间上限的)

  • 当线程执行 wait()、join() 或 LockSupport.park() 方法后,线程进入等待状态。
  • 在这个状态下,线程需要等待其他线程执行特定的操作(如通知或中断)才能继续。
  • 等待状态的线程不会被分配 CPU 时间片。
public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{while(true) {}});System.out.println(thread.getState());thread.start();thread.join();}
}

在这里插入图片描述
发现main线程是waiting。

• TIMED_WAITING:
时间阻塞(这个等待是有时间上限的),不参与CPU调度

public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{while(true) {try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});System.out.println(thread.getState());thread.start();Thread.sleep(1000);System.out.println(thread.getState());}
}

• TERMINATED:

  • 当线程的 run() 方法执行完毕,或者线程被 stop() 方法(已废弃)强制停止,或者线程抛出未捕获的异常导致运行结束时,线程进入终止状态。
  • 在这个状态下,线程已经结束执行,不再消耗任何资源。
public class Demo7 {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{for(int i=0;i<3;i++) {System.out.println("Hello Thread");}});System.out.println(thread.getState());thread.start();Thread.sleep(6000);System.out.println(thread.getState());}
}

2.5 后台线程和前台线程

前台线程:一般我们创建的线程都是前台线程,只要前台线程不结束,JVM就不会退出。
后台线程:也称守护线程,后台线程一般都是辅助性的任务,如果前台线程全部结束,即使还有后台线程在运行,JAM也会退出。

public class Demo8 {public static void main(String[] args) {Thread thread1=new Thread(()->{for(int i=0;i<2;i++){System.out.println("Hello Thread");}});thread1.start();System.out.println(thread1.isDaemon());//false 说明他不是守护线程Thread thread2=new Thread(()->{for(int i=0;i<2;i++){System.out.println("Hello Thread");}});thread2.setDaemon(true);thread2.start();System.out.println(thread2.isDaemon());//true}
}

2.6 休眠线程

在这里插入图片描述
下面那个可以达到纳秒级别,这种适用于军工,航天等之类,一把情况下用不到。
在这里插入图片描述
这里还有一个需要注意的是:由于 Runnable 接口的 run 方法没有 throws 子句,所以这里只能用try-catch 来捕获异常。

2.7 线程等待

在这里插入图片描述

public class Demo10 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{for (int i = 0; i < 3; i++){System.out.println("Hello Thread");}});thread.start();thread.join();System.out.println("Hello main");}
}

先执行thread线程,thread线程执行完,再执行main线程。为了防止死等,也可以设置等待时间。

2.8 终止线程

让run方法尽快结束。

2.8.1 自定义标志位终止线程
public class Demo11 {public static  boolean flag=true;public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{while(flag){System.out.println("Hello Thread");}System.out.println("Bye Bye Thread");});thread.start();Thread.sleep(1000);flag=false;}
}

将flag设置为全局变量,这里就是匿名内部类访问外部类,而不是变量捕获。
为什么不可以将flag设置为局部变量?
在这里插入图片描述

很有可能是main线程已经执行完,已经将flag销毁了,但是Thread线程中还没执行到while(flag)…

2.8.2 使用自带标志位终止线程

在这里插入图片描述
Java自带标志位来结束终止线程。先使用Thread.currentThread()来获取当前线程,在.isInterrupted()获取标志位。然后再主进程中调用interrupte()方法来将标志位值修改为true。

public class Demo12 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (!Thread.currentThread().interrupted()) {System.out.println("Hello Thread");}System.out.println("Bye Bye Thread");});thread.start();Thread.sleep(1000);thread.interrupt();}
}

调用interrupte()方法,不仅会设置标志位,还会提前唤起sleep阻塞

public class Demo12 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() ->{while (!Thread.currentThread().isInterrupted()) {System.out.println("hahah");try {Thread.sleep(1000);} catch (InterruptedException e) {//1.不操作继续执行线程(因为sleep唤醒后会又将标志位改为true)e.printStackTrace();//2.结束线程break;//3.进行其它操作}}});thread.start();Thread.sleep(1000);thread.interrupt();}
}

此篇博客的全部代码!!!

相关文章:

【JAVAEE】多线程

【JAVAEE】多线程 一、进程1.1 进程的定义1.2 进程和线程的联系 二、线程2.1 JConsole工具2.2 创建线程2.2.1 Thread类&#xff0c;start&#xff08;&#xff09;&#xff0c;run&#xff08;&#xff09;2.2.2 继承Thread类2.2.3 实现Runnable接口2.2.4 匿名内部类2.2.5 使用…...

5.10 P-Tuning v2:多层级提示编码的微调革新

P-Tuning v2:多层级提示编码的微调革新 一、技术架构解析 #mermaid-svg-4Wy6vkXZi67hY9PZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-4Wy6vkXZi67hY9PZ .error-icon{fill:#552222;}#mermaid-svg-4Wy6vkXZi67h…...

LLM中的Benchmark是什么

LLM中的Benchmark是什么 “DeepSeek推动价值重估Benchmark” DeepSeek这家公司或其相关技术的发展,促使Benchmark这家机构对相关资产或企业的价值进行重新评估。“Benchmark”在这里是一家研究机构或金融分析机构。 “Benchmark”常见的意思是“基准;水准点,基准点”,作…...

PMP项目管理—整合管理篇—6.实施整体变更控制

文章目录 基本信息4W1HITTO输入工具与技术输出 变更请求请求时间修改内容变更来源变更类型 实施已批准变更的形式纠正措施预防措施缺陷补救更新 变更控制工具 实施整体变更控制规则态度规则项目变更控制委员会&#xff08;CCB&#xff09;变更应对分析计划、执行期后期或收尾 基…...

深度学习之特征提取

前言 深度学习就是把输入转换成一个高维的向量&#xff0c;之后利用这个向量去完成分类、回归等任务。 深度学习特征工程知识图谱 1. 特征提取的本质 核心目标&#xff1a;将原始数据→高维语义特征向量 监督驱动&#xff1a;标签决定特征提取方向 典型架构&#xff1a; …...

Gurobi 并行计算的一些问题

最近尝试用 gurobi 进行并行计算&#xff0c;即同时用多个 cpu 核计算 gurobi 的 model&#xff0c;但是发现了不少问题。总体来看&#xff0c;gurobi 对并行计算的支持并不是那么好。 gurobi 官方对于并行计算的使用在这个网址&#xff0c;并有下面的大致代码&#xff1a; i…...

堆、栈、最小堆

堆是什么 结构属性 堆是一棵完全二叉树&#xff0c;即除最后一层外&#xff0c;其他层节点均填满&#xff0c;且最后一层节点从左到右连续分布。 排序属性&#xff1a; 根据类型不同&#xff0c;堆分为&#xff1a; 最大堆&#xff08;Max-Heap&#xff09; &#xff1a;每…...

基于 Spring AI 的 HIS 系统智能化改造

【Spring AI 的背景与现状】 Spring AI 是 Spring 生态里整的一个新活儿&#xff0c;专门给开发者提供搞 AI 驱动的应用的工具和框架。虽然 Spring AI 已经鼓捣了挺长时间&#xff0c;但截至现在&#xff08;2025年2月&#xff09;&#xff0c;它还没正式发布。不过&#xff0…...

React进阶之前端业务Hooks库(五)

前端业务Hooks库 Hooks原理useStateuseEffect上述问题useState,useEffect 复用的能力练习:怎样实现一套React过程中的hooks状态 & 副作用Hooks原理 不能在循环中、条件判断、子函数中调用,只能在函数最外层去调用useEffect 中,deps 为空,执行一次useState 使用: imp…...

常见锁类型介绍

下面结合代码详细介绍 Mutex、RW Lock、Futex、自旋锁、信号量、条件变量 和 synchronized&#xff0c;并分析它们的适用场景、特点以及为什么这些锁适用于特定场景。我们将从锁的实现机制和性能特点出发&#xff0c;解释其适用性。 1. Mutex&#xff08;互斥锁&#xff09; 代…...

Java中,Scanner和System.out超时的解决方法及原理

ACM 模式的原理 在输入输出的时候&#xff0c;会先将输入输出的东西放在一个文件里&#xff0c;这个文件也叫做 IO 设备 为什么 Scanner 会慢 new 一个 Scanner &#xff0c;在 Scanner 里面调用 next 的时候&#xff0c;程序会直接访问 IO 设备。在调用一个 next 的时候&…...

一种数据高效具身操作的原子技能库构建方法

25年1月来自京东、中科大、深圳大学、海尔集团、地平线机器人和睿尔曼智能科技的论文“An Atomic Skill Library Construction Method for Data-Efficient Embodied Manipulation”。 具身操控是具身人工智能领域的一项基本能力。尽管目前的具身操控模型在特定场景下表现出一定…...

云创智城YunCharge 新能源二轮、四轮充电解决方案(云快充、万马爱充、中电联、OCPP1.6J等多个私有单车、汽车充电协议)之新能源充电行业系统说明书

云创智城YunCharge 新能源充电行业系统说明书 ⚡官方文档 ⚡官网地址 1. 引言 随着全球环境保护和能源危机的加剧&#xff0c;新能源汽车行业得到了快速发展&#xff0c;充电基础设施建设也随之蓬勃发展。新能源充电行业系统旨在提供高效、便捷的充电服务&#xff0c;满足电…...

JVM垃圾回收器深度底层原理分析与知识体系构建

一、垃圾回收的基本步骤 标记&#xff08;Marking&#xff09; 从GC Roots&#xff08;如虚拟机栈、方法区静态变量、本地方法栈等&#xff09;出发&#xff0c;遍历对象引用链&#xff0c;标记所有可达对象为存活对象&#xff0c;未被标记的则视为垃圾。此阶段需暂停用户线程&…...

30.[前端开发-JavaScript基础]Day07-数组Array-高阶函数-日期Date-DOM

JavaScript的DOM操作 &#xff08;一&#xff09; 1 什么是DOM&#xff1f; 认识DOM和BOM 深入理解DOM 2 认识DOM Tree DOM Tree的理解 3 DOM的整体结构 DOM的学习顺序 DOM的继承关系图 document对象 4 节点、元素导航 节点&#xff08;Node&#xff09;之间的导航&…...

IP、网关、子网掩码、DNS 之间的关系详解

IP、网关、子网掩码、DNS 之间的关系详解 在计算机网络中&#xff0c;IP、网关、子网掩码和 DNS 是几个关键概念&#xff0c;它们协同工作&#xff0c;共同保障网络通信的顺畅。本文将详细探讨它们之间的关系。 一、IP 地址 IP 地址是网络中设备的唯一标识&#xff0c;如同现…...

【Day50 LeetCode】图论问题 Ⅷ

一、图论问题 Ⅷ 1、dijkstra算法 堆优化 采用堆来优化&#xff0c;适合节点多的稀疏图。代码如下&#xff1a; # include<iostream> # include<vector> # include<list> # include<queue> # include<climits>using namespace std;class myco…...

结构体介绍及内存大小分配问题

结构体 一.结构体的介绍1.1结构体的声明1.2匿名结构体1.3结构的自引用1.4使用 typedef 简化结构体类型名 二.结构体内存对齐2.1内存对齐规则2.2结构体内存对齐原因2.3修改默认对齐数 在 C 语言中&#xff0c;结构体&#xff08;struct&#xff09;是一种用户自定义的数据类型&a…...

halcon 条形码、二维码识别、opencv识别

一、条形码 函数介绍 create_bar_code_model * 1.创建条码读取器的模板 * 参数一&#xff1a;通用参数的名称&#xff0c;针对条形码模型进行调整。默认值为空 * 参数二&#xff1a;针对条形码模型进行调整 * 参数三&#xff1a;条形码模型的句柄。 create_bar_code_model (…...

Vue框架的使用 搭建打包 Vue的安全问题(Xss,源码泄露)

前言 什么是Vue&#xff1f; Vue是轻量级的js框架 可以帮助我们一键构造网站&#xff0c;打包app程序等 Vue的基本使用 1、构造框架并启用 新建一个 目录 使用终端切换到当前的目录 创建vue项目 第一个弹出使用语法我们选择是 剩下的全选择否 发现创建好了 接着进行…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...