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是把线程和任务合并在了一起,方法2是把线程和任务分开了。
- 用Runnable更容易把线程池等高级API配合。
- 用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
- 调用sleep会让当前线程从Running进入Timed Waiting状态。
- 其它线程可以使用interrupt方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException。
- 睡眠结束后的线程未必立刻得到执行。
- 建议用TimeUnit的sleep代替Thread的sleep来获得更好的可读性。
yield
- 调用yield会让当前线程从Running进入Runnable状态,然后调度执行其它同优先级的线程。如果这时没有同优先级的线程,那么不能保证让当前线程暂停的效果。
- 具体的实现依赖于操作系统的任务调度器。
线程优先级
- 线程优先级会提示调度器优先调度该线程,但仅仅是一个提示,调度器可以忽略它。
- 如果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会失效。
不推荐的方法:
- stop() 停止线程运行
- suspend() 挂起(暂停)线程运行
- 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 枚举,分为六种状态。
- NEW 线程刚被创建,但是还没有调用start()方法。
- RUNNABLE当调用了start()方法之后,注意,Java API层面的RUNNABLE状态涵盖了操作系统层面的可运行状态、运行状态和阻塞状态(由于BIO导致的线程阻塞,在Java里无法区分,仍然认为是可运行)。
- BLOCKED、WAITING、TIMED_WAITING都是Java API层面对阻塞状态的细分,后面会在状态转换一节详述。
- TERMINATED当线程代码运行结束。
相关文章:
JUC并发编程——Java线程(一)
文章目录 1. 线程的创建1.1 方法1: 直接使用Thread1.2 方法2:使用Runnable配合Thread1.3 方法3: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小车亚博官网例子延时性基本上跑完了,发现自己一些基础Python语法还不熟悉。 本节学习循环: while\for\break\continue 1. while 循环 while 循环会在条件表达式为真时,重复执行一段代码块,直到条件表达式变为假。 格式&am…...
【SQL教程|07】sql中条件查询where用法示例
SQL WHERE 条件查询教程 在SQL中,WHERE 条件用于在 SELECT 语句后过滤结果集,只返回符合条件的记录。它帮助我们从大量数据中提取所需的信息。以下是使用 WHERE 条件的逐步指南。 1. 基本语法 SELECT [字段] FROM [表] WHERE [条件];SELECT:…...
项目实战(13)-双频RFID语音播报阅读器
一. 产品简介: 1、项目背景是在实际应用中需要读取射频标签ID,但是市面上这种标签类型不统一;有的频段是125KHz,高频的是13.56MHz。所以需要一个读卡模块实现这两种卡的识别读取。 2、板子核心处理器是STM32F407,显示…...
基本控制环节的幅频和相频特性
基本控制环节的幅频和相频特性 在控制系统中,不同类型的控制环节具有各自独特的动态特性。为了研究这些环节对信号的影响,通常需要分析其频率响应特性,即幅频特性和相频特性。以下对几种常见的基本控制环节进行逐一分析。 1. 比例环节 比例…...
vue3 ref和reactive的区别
在 Vue 3 中,ref 和 reactive 是两种用于创建响应式数据的 API,但它们的使用场景和实现方式有一些区别。用大白话来说,它们的区别可以这样理解: 1. ref:适合处理简单数据 是什么:ref 是用来包装一个基本类…...
Maven 构建报告与文档生成
Maven 是一种强大的构建工具,它不仅可以帮助我们构建和管理项目,还提供了生成项目报告和文档的功能。通过 Maven 的插件,我们可以自动生成代码文档(如 Javadoc),执行测试并生成测试报告,以及其他…...
复制内容到软件内部,软件内部内容不刷新
在Windows 10系统中,遇到复制内容后需要点击任务栏才能刷新软件内容的问题,可能是由于软件自身刷新机制、系统资源管理或显卡驱动等原因导致。以下是逐步解决方案 1. 检查软件设置 开启自动刷新功能:某些软件(如文件管理器、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 然后从哪个接口可以获取图片文件呢? 根据您的问题,我可以为您提供以下信息: 一旦您获得了imageId,您可以使用以下几个API接口来获取图片文件: 获取文档图片: Get document images GET https://api.sumsub.com/resources/inspections/{inspection…...
DeepSeek + Mermaid编辑器——常规绘图
下面这张图出自:由清华大学出品的 《DeepSeek:从入门到精通》。 作为纯文本生成模型,DeepSeek虽不具备多媒体内容生成接口,但其开放式架构允许通过API接口与图像合成引擎、数据可视化工具等第三方系统进行协同工作,最终…...
ARM64 Trust Firmware [五 ]
本章介绍 ATF 中的 Runtime Service 是如何定义和被调用的。 要了解 SMC,必须从 SMC 指令本身开始,其指令如下图: 指令格式为:SMC #<imm>,从官方文档了解到该指令只能在 EL1 以及更高的异常等级上调用ÿ…...
Excel核心函数VLOOKUP全解析:从入门到精通
一、函数概述 VLOOKUP是Excel中最重要且使用频率最高的查找函数之一,全称为Vertical Lookup(垂直查找)。该函数主要用于在数据表的首列查找特定值,并返回该行中指定列的对应值。根据微软官方统计,超过80%的Excel用户在…...
KTransformers如何通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度?
KTransformers通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度,具体体现在以下几个方面: 内核级优化: KTransformers采用了高效的内核级优化技术,包括对Transformer模型中的关键操作进行优化。例如…...
审计级别未启用扩展模式导致查询 DBA_AUDIT_TRAIL 时 SQL_TEXT 列为空
如果查询 DBA_AUDIT_TRAIL 时发现 SQL_TEXT 列为空,但其他字段(如 OS_USERNAME、USERNAME、TIMESTAMP 等)有数据,可能是由于以下原因之一。以下是可能的原因及解决方法: 1. 审计级别未启用扩展模式 默认情况下&#x…...
微信小程序项目 video 组件失效问题,无法播放本地视频
问题与处理策略 问题描述 <video src"../../assets/video/test-video.mp4" controls style"width: 100%; height: 300px;"></video>在微信小程序项目中,上述 video 组件失效,视频无法加载,无法播放本地视频…...
若依-@Excel新增注解numberFormat
Excel注解中原本的scale会四舍五入小数,导致进度丢失 想要的效果 显示的时候保留两个小数真正的数值是保留之前的数值 还原过程 若以中有一個專門的工具类,用来处理excel的 找到EXCEL导出方法exportExcel()找到writeSheet,写表格的方法找到填充数据的方法…...
网络安全行业有哪些公司
只是简单做一下网络安全公司梳理,不作点评,下列排名不分先后。 一、常见的网络安全公司 1、天融信 天融信(002212.SZ)创始于1995年,是上市公司中成立最早的网络安全企业,亲历中国网络安全产业的发展历程…...
10分钟完成10倍速视频硬字幕提取:SubtitleOCR颠覆传统工作流
10分钟完成10倍速视频硬字幕提取:SubtitleOCR颠覆传统工作流 【免费下载链接】SubtitleOCR 快如闪电的硬字幕提取工具。仅需苹果M1芯片或英伟达3060显卡即可达到10倍速提取。A very fast tool for video hardcode subtitle extraction 项目地址: https://gitcode.…...
如何快速获取八大网盘直链下载链接:新手友好的完整教程
如何快速获取八大网盘直链下载链接:新手友好的完整教程 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼…...
Nexu:开发环境即代码,实现团队开发环境标准化与一键部署
1. 项目概述:从零到一理解Nexu最近在开源社区里,一个名为“nexu-io/nexu”的项目引起了我的注意。乍一看这个标题,你可能会有点摸不着头脑:这到底是做什么的?是某种新的开发框架,还是一个工具链?…...
终极指南:用RPFM快速创建你的第一个《全面战争》模组
终极指南:用RPFM快速创建你的第一个《全面战争》模组 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt6 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地址: https://gitc…...
立创商城旧版TM1650按键不灵?手把手教你开启扫描模式(附最新数据手册对比)
立创商城旧版TM1650按键不灵?手把手教你开启扫描模式(附最新数据手册对比) 在嵌入式开发中,使用过时的技术文档往往会导致各种难以排查的问题。最近不少开发者反馈,在使用立创商城提供的旧版TM1650数据手册时ÿ…...
Tiny11Builder技术深度解析:基于DISM的Windows 11精简镜像构建实战指南
Tiny11Builder技术深度解析:基于DISM的Windows 11精简镜像构建实战指南 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder Tiny11Builder是一套基于Power…...
5大必备星露谷物语模组:彻底改变你的农场生活体验
5大必备星露谷物语模组:彻底改变你的农场生活体验 【免费下载链接】StardewMods Mods for Stardew Valley using SMAPI. 项目地址: https://gitcode.com/gh_mirrors/st/StardewMods 还在为《星露谷物语》中繁琐的农场管理而烦恼吗?想要更智能、更…...
SharpKeys键盘重映射终极指南:3分钟掌握Windows键位自定义
SharpKeys键盘重映射终极指南:3分钟掌握Windows键位自定义 【免费下载链接】sharpkeys SharpKeys is a utility that manages a Registry key that allows Windows to remap one key to any other key. 项目地址: https://gitcode.com/gh_mirrors/sh/sharpkeys …...
如何让微信聊天记录真正属于你?WeChatMsg数据自主管理完全指南
如何让微信聊天记录真正属于你?WeChatMsg数据自主管理完全指南 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/…...
GAPERON模型:多语言与代码任务的协同优化实践
1. 项目背景与核心价值GAPERON模型是当前NLP领域一个颇具创新性的技术方案,它通过特定的微调策略,在保持英语任务性能的同时显著提升了多语言处理和代码相关任务的表现。这种模型架构特别适合需要同时处理自然语言和编程语言的混合场景,比如自…...
