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

JUC并发编程——Java线程(一)

文章目录

  • 1. 线程的创建
    • 1.1 方法1: 直接使用Thread
    • 1.2 方法2:使用Runnable配合Thread
    • 1.3 方法3:FutureTask配合Thread
  • 2. 线程运行
    • 2.1 原理
    • 2.2 常见方法
      • 2.2.1 start与run
      • 2.2.2 sleep与yield
      • 2.2.3 join
      • 2.2.4 interrupt
  • 3. 主线程和守护线程
  • 4. 线程状态
    • 4.1 五种状态
    • 4.2 六种状态


1. 线程的创建

1.1 方法1: 直接使用Thread

Thread t = new Thread(){@Overridepublic void run(){// 要执行的任务}
};
// 启动线程
t.start();

1.2 方法2:使用Runnable配合Thread

把 [线程] 和 [任务] (要执行的代码)分开

  • Thread代表线程
  • Runnable可执行的任务(线程需要执行的代码)
Runnable runnable = new Runnable() {public void run(){// 要执行的任务}
}
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start(); 

java8以后可以使用lambda精简代码

Runnable r = () -> {log.debug("running");
};
Thread t = new Thread(r, "t2");
t.start();

小结:

  1. 方法1是把线程和任务合并在了一起,方法2是把线程和任务分开了。
  2. 用Runnable更容易把线程池等高级API配合。
  3. 用Runnable让任务类脱离了Thread继承体系,更灵活。

1.3 方法3:FutureTask配合Thread

FutureTask能够接收Callable类型的参数,用来处理有返回结果的情况。

FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>(){@Overridepublic Integer call() throws Exception {log.debug("running");Thread.sleep(1000);return 100;}
});Thread t = new Thread(task);
t.start();log.debug("{}", task.get());

2. 线程运行

2.1 原理

栈与栈帧
JVM由堆、栈、方法区所组成,其中栈内存给线程使用,每个线程启动后哦,虚拟机就会为其分配一块栈内存。

  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存。
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。

线程上下文切换(Thread Context Switch)
因为以下一些原因导致cpu不再执行当前的线程,转而执行另一个线程的代码

  • 线程cpu时间片用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了sleep、yield、wait、join、park、sychronized、lock等方法程序

当Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java中对应的概念就是程序计数器,它的作用是记住下一条jvm指令的执行地址,是线程私有的。

  • 状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等。
  • Context Switch频繁发生会影响性能。

多线程

2.2 常见方法

2.2.1 start与run

  • 启动线程必须要调用start(),不然对性能没影响。
  • start()不能多次调用
public class Test4{public static void main(String[] args){Thread t1 = new Thread("t1") {@Overridepublic void run() {log.debug("running....");}};// t1.run();t1.start();}
}

2.2.2 sleep与yield

sleep

  1. 调用sleep会让当前线程从Running进入Timed Waiting状态。
  2. 其它线程可以使用interrupt方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException。
  3. 睡眠结束后的线程未必立刻得到执行。
  4. 建议用TimeUnit的sleep代替Thread的sleep来获得更好的可读性。

yield

  1. 调用yield会让当前线程从Running进入Runnable状态,然后调度执行其它同优先级的线程。如果这时没有同优先级的线程,那么不能保证让当前线程暂停的效果。
  2. 具体的实现依赖于操作系统的任务调度器。

线程优先级

  • 线程优先级会提示调度器优先调度该线程,但仅仅是一个提示,调度器可以忽略它。
  • 如果cpu比较忙,那么优先级高的线程会获得更多的时间片,但cpu闲时,优先级几乎没作用。

sleep实现
在没有利用cpu来计算时,不要让while(true)空转浪费cpu,这时可以用yield或sleep来让出cpu的使用权给其他程序。

while(true){try{Thread.sleep(50);} catch (InterruptedException e){e.printStackTrace();}
}
  • 可以用wait 或 条件变量达到类似的效果。
  • 不同的是,后两种都需要加锁,并且需要相应的唤醒操作,一般适用于要进行同步的场景。
  • sleep适用于无需锁同步的场景。

2.2.3 join

等待线程运行结束

t1.start();
t1.join();

应用之同步(案例1)
以调用方角度来讲,如果

  • 需要等待结果返回,才能继续运行就是同步
  • 不需要等待结果返回,就能继续运行就是异步

2.2.4 interrupt

打断sleep,wait,join的线程
eg:打断sleep的线程,会清空打断状态。

private static void test1() throws InterruptedException {Thread t1 = new Thread(() ->{sleep(1);}, "t1");t1.start();sleep(0.5);t1.interrupt();log.debug("打断状态:{}", t1.isInterrupted());
}

eg:打断正常运行的线程,不会清空打断状态。

两阶段终止模式
在一个线程T1中如何“优雅”终止T2,即给T2一个善后的机会。

错误思路如下:

  • 使用线程对象stop()方法停止线程
    • stop方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,其他线程将永远无法获取锁。
  • 使用System.exit(int)方法停止线程
    • 目的仅是停止一个线程,但这种做法会让整个程序都停止。

在这里插入图片描述

public class Test3{public static void main(String[] args){TwoPhaseTermination tpt = new TwoPhaseTermination();tpt.start();	Thread.sleep(3500);tpt.stop();}
}class TwoPhaseTermination{private Thread monitor;// 启动监控线程public void start(){monitor = new Thread(() -> {while(true){Thread current = Thread.currentThread();if(current.isInterrupted()){log.debug("料理后事");break;}try{Thread.sleep(1000); // 情况1log.debug("执行监控记录"); // 情况2} catch(InterruptedExcetion e){e.printStackTrace();// 重新设置打断标记current.interrupt();}}}); }// 停止监控线程public void stop(){monitor.intterupt();}
}

打断park线程,不会清空打断状态。
如果打断标记已经是true,则park会失效。

不推荐的方法:

  1. stop() 停止线程运行
  2. suspend() 挂起(暂停)线程运行
  3. resume() 恢复线程运行

3. 主线程和守护线程

默认情况下,Java进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强行结束。

log.debug("开始运行...");
Thread t1 = new Thread(() -> {log.debug("开始运行...");sleep(2);log.debug("运行结束...");
}, "daemon");
t1.setDaemon(true);
t1.start();sleep(1);
log.debug("运行结束...");

4. 线程状态

4.1 五种状态

这是从操作系统层面来描述的
在这里插入图片描述

  • 初始状态: 仅仅在语言层面创建了线程对象,还未与操作系统线程关联。
  • **可运行状态:**指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行
  • 运行状态: 指获取了CPU时间片运行中的状态。
    • 当CPU时间片用完,会从 运行状态 切换至 可运行状态, 会导致线程的上下文切换
  • 阻塞状态:
    • 如果调用了阻塞API,如BIO读写文件,这时该线程实际不会用到CPU,会导致线程上下文切换,进入阻塞状态
    • 等BIO操作完毕,会由操作系统唤醒阻塞的线程,转换至可运行状态
    • 可运行状态的区别是,对阻塞状态的线程来说只要它们一直不唤醒,调度器就一直不回考虑调度它们。
  • **终止状态:**表示线程已经执行完毕,生命周期已经技术,不会再转换为其它状态。

4.2 六种状态

这是从Java API层面来描述的。
在这里插入图片描述
根据Thread.State 枚举,分为六种状态。

  1. NEW 线程刚被创建,但是还没有调用start()方法。
  2. RUNNABLE当调用了start()方法之后,注意,Java API层面的RUNNABLE状态涵盖了操作系统层面的可运行状态运行状态阻塞状态(由于BIO导致的线程阻塞,在Java里无法区分,仍然认为是可运行)。
  3. BLOCKED、WAITING、TIMED_WAITING都是Java API层面对阻塞状态的细分,后面会在状态转换一节详述。
  4. TERMINATED当线程代码运行结束。

相关文章:

JUC并发编程——Java线程(一)

文章目录 1. 线程的创建1.1 方法1&#xff1a; 直接使用Thread1.2 方法2&#xff1a;使用Runnable配合Thread1.3 方法3&#xff1a;FutureTask配合Thread 2. 线程运行2.1 原理2.2 常见方法2.2.1 start与run2.2.2 sleep与yield2.2.3 join2.2.4 interrupt 3. 主线程和守护线程4. …...

Python入门笔记3

ros小车亚博官网例子延时性基本上跑完了&#xff0c;发现自己一些基础Python语法还不熟悉。 本节学习循环&#xff1a; while\for\break\continue 1. while 循环 while 循环会在条件表达式为真时&#xff0c;重复执行一段代码块&#xff0c;直到条件表达式变为假。 格式&am…...

【SQL教程|07】sql中条件查询where用法示例

SQL WHERE 条件查询教程 在SQL中&#xff0c;WHERE 条件用于在 SELECT 语句后过滤结果集&#xff0c;只返回符合条件的记录。它帮助我们从大量数据中提取所需的信息。以下是使用 WHERE 条件的逐步指南。 1. 基本语法 SELECT [字段] FROM [表] WHERE [条件];SELECT&#xff1a…...

项目实战(13)-双频RFID语音播报阅读器

一. 产品简介&#xff1a; 1、项目背景是在实际应用中需要读取射频标签ID&#xff0c;但是市面上这种标签类型不统一&#xff1b;有的频段是125KHz&#xff0c;高频的是13.56MHz。所以需要一个读卡模块实现这两种卡的识别读取。 2、板子核心处理器是STM32F407&#xff0c;显示…...

基本控制环节的幅频和相频特性

基本控制环节的幅频和相频特性 在控制系统中&#xff0c;不同类型的控制环节具有各自独特的动态特性。为了研究这些环节对信号的影响&#xff0c;通常需要分析其频率响应特性&#xff0c;即幅频特性和相频特性。以下对几种常见的基本控制环节进行逐一分析。 1. 比例环节 比例…...

vue3 ref和reactive的区别

在 Vue 3 中&#xff0c;ref 和 reactive 是两种用于创建响应式数据的 API&#xff0c;但它们的使用场景和实现方式有一些区别。用大白话来说&#xff0c;它们的区别可以这样理解&#xff1a; 1. ref&#xff1a;适合处理简单数据 是什么&#xff1a;ref 是用来包装一个基本类…...

Maven 构建报告与文档生成

Maven 是一种强大的构建工具&#xff0c;它不仅可以帮助我们构建和管理项目&#xff0c;还提供了生成项目报告和文档的功能。通过 Maven 的插件&#xff0c;我们可以自动生成代码文档&#xff08;如 Javadoc&#xff09;&#xff0c;执行测试并生成测试报告&#xff0c;以及其他…...

复制内容到软件内部,软件内部内容不刷新

在Windows 10系统中&#xff0c;遇到复制内容后需要点击任务栏才能刷新软件内容的问题&#xff0c;可能是由于软件自身刷新机制、系统资源管理或显卡驱动等原因导致。以下是逐步解决方案 1. 检查软件设置 开启自动刷新功能&#xff1a;某些软件&#xff08;如文件管理器、IDE、…...

C# 实现完善 Excel 不规则合并单元格数据导入

目录 功能完善 Excel与DataSet的映射关系 运行环境 Excel DCOM 配置 设计实现 组件库引入 方法更新 返回值 参数设计 打开数据源并计算Sheets 拆分合并的单元格 创建DataTable 将单元格数据写入DataTable 删除虚拟列 总结 功能完善 在我的文章 《C#实现Excel…...

C#功能测试

List 内部元素为引用 src[0]为"11" List<Source> src new List<Source>(); src.Add(new Source() { Name "1", Age 1, Description "1" }); src.Add(new Source() { Name "2", Age 2, Description "2"…...

C++17并行化加速STL算法——std::execution

C17 并行化STL算法 文章目录 C17 并行化STL算法概念环境准备工具类 并行算法 - 使用并行算法 - 执行策略总览选择标准详细介绍顺序执行 seq并行化顺序执行 par并行化乱序执行 par_unseq 并行算法 - 异常处理可以不使用并行算法并行算法 - 限制并行算法有哪些原有算法17引入新算…...

从sumsub获取用户图片

已经拿到了imageid 然后从哪个接口可以获取图片文件呢&#xff1f; 根据您的问题,我可以为您提供以下信息: 一旦您获得了imageId,您可以使用以下几个API接口来获取图片文件: 获取文档图片: Get document images GET https://api.sumsub.com/resources/inspections/{inspection…...

DeepSeek + Mermaid编辑器——常规绘图

下面这张图出自&#xff1a;由清华大学出品的 《DeepSeek&#xff1a;从入门到精通》。 作为纯文本生成模型&#xff0c;DeepSeek虽不具备多媒体内容生成接口&#xff0c;但其开放式架构允许通过API接口与图像合成引擎、数据可视化工具等第三方系统进行协同工作&#xff0c;最终…...

ARM64 Trust Firmware [五 ]

本章介绍 ATF 中的 Runtime Service 是如何定义和被调用的。 要了解 SMC&#xff0c;必须从 SMC 指令本身开始&#xff0c;其指令如下图&#xff1a; 指令格式为&#xff1a;SMC #<imm>&#xff0c;从官方文档了解到该指令只能在 EL1 以及更高的异常等级上调用&#xff…...

Excel核心函数VLOOKUP全解析:从入门到精通

一、函数概述 VLOOKUP是Excel中最重要且使用频率最高的查找函数之一&#xff0c;全称为Vertical Lookup&#xff08;垂直查找&#xff09;。该函数主要用于在数据表的首列查找特定值&#xff0c;并返回该行中指定列的对应值。根据微软官方统计&#xff0c;超过80%的Excel用户在…...

KTransformers如何通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度?

KTransformers通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度&#xff0c;具体体现在以下几个方面&#xff1a; 内核级优化&#xff1a; KTransformers采用了高效的内核级优化技术&#xff0c;包括对Transformer模型中的关键操作进行优化。例如…...

审计级别未启用扩展模式导致查询 DBA_AUDIT_TRAIL 时 SQL_TEXT 列为空

如果查询 DBA_AUDIT_TRAIL 时发现 SQL_TEXT 列为空&#xff0c;但其他字段&#xff08;如 OS_USERNAME、USERNAME、TIMESTAMP 等&#xff09;有数据&#xff0c;可能是由于以下原因之一。以下是可能的原因及解决方法&#xff1a; 1. 审计级别未启用扩展模式 默认情况下&#x…...

微信小程序项目 video 组件失效问题,无法播放本地视频

问题与处理策略 问题描述 <video src"../../assets/video/test-video.mp4" controls style"width: 100%; height: 300px;"></video>在微信小程序项目中&#xff0c;上述 video 组件失效&#xff0c;视频无法加载&#xff0c;无法播放本地视频…...

若依-@Excel新增注解numberFormat

Excel注解中原本的scale会四舍五入小数&#xff0c;导致进度丢失 想要的效果 显示的时候保留两个小数真正的数值是保留之前的数值 还原过程 若以中有一個專門的工具类&#xff0c;用来处理excel的 找到EXCEL导出方法exportExcel()找到writeSheet,写表格的方法找到填充数据的方法…...

网络安全行业有哪些公司

只是简单做一下网络安全公司梳理&#xff0c;不作点评&#xff0c;下列排名不分先后。 一、常见的网络安全公司 1、天融信 天融信&#xff08;002212.SZ&#xff09;创始于1995年&#xff0c;是上市公司中成立最早的网络安全企业&#xff0c;亲历中国网络安全产业的发展历程…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...

Django RBAC项目后端实战 - 03 DRF权限控制实现

项目背景 在上一篇文章中&#xff0c;我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统&#xff0c;为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...

MeshGPT 笔记

[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭&#xff01;_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...

react更新页面数据,操作页面,双向数据绑定

// 路由不是组件的直接跳转use client&#xff0c;useEffect&#xff0c;useRouter&#xff0c;需3个结合&#xff0c; use client表示客户端 use client; import { Button,Card, Space,Tag,Table,message,Input } from antd; import { useEffect,useState } from react; impor…...