javaEE(2)多线程初阶
1 线程的核心概念1.1 进程与线程的定义进程是操作系统进行资源分配的最小单位一个正在运行的应用程序对应一个独立进程拥有独立的内存地址空间。线程是操作系统进行任务调度的最小单位是进程内部的一条独立执行流。一个进程至少包含一个主线程同一进程内的多个线程共享进程的内存资源与文件资源。1.2 进程与线程的核心差异对比维度进程线程资源定位系统分配资源的最小单位系统调度 CPU 执行的最小单位内存空间进程间内存相互隔离独立寻址同一进程内线程共享堆内存与方法区各线程私有栈空间与程序计数器故障影响单个进程崩溃不影响其他进程单个线程异常可能导致整个进程终止调度开销创建、销毁、上下文切换开销较高创建、销毁、切换开销远低于进程1.3 Java线程与操作系统线程的关系线程是操作系统内核提供的原生能力Java 标准库中的java.lang.Thread类是对操作系统线程 API 的抽象与封装。调用线程对象的start()方法才会通过操作系统内核创建并启动一条原生线程重写run()方法仅用于定义线程的执行逻辑直接调用run()不会创建新线程代码仍在当前调用线程中串行执行。2 线程的创建方式2.1 继承Thread类通过继承Thread类并重写run()方法定义线程任务创建子类实例后调用start()启动线程。该方式受 Java 单继承机制限制适用于线程类无需继承其他父类的场景。classCustomThreadextendsThread{Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName() 执行中);}}publicclassThreadCreateDemo1{publicstaticvoidmain(String[]args){CustomThreadthreadnewCustomThread();thread.start();}}2.2 实现Runnable接口通过实现Runnable接口定义任务逻辑再将任务实例传入Thread构造方法。该方式将任务定义与线程控制解耦支持类继承其他父类是更推荐的实现方式。classCustomTaskimplementsRunnable{Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName() 执行中);}}publicclassThreadCreateDemo2{publicstaticvoidmain(String[]args){ThreadthreadnewThread(newCustomTask());thread.start();}}2.3 匿名内部类实现对于一次性使用的线程任务可通过匿名内部类快速创建无需单独定义实现类。publicclassThreadCreateDemo3{publicstaticvoidmain(String[]args){// 继承Thread的匿名内部类Threadt1newThread(){Overridepublicvoidrun(){System.out.println(匿名Thread实现);}};t1.start();// 实现Runnable的匿名内部类Threadt2newThread(newRunnable(){Overridepublicvoidrun(){System.out.println(匿名Runnable实现);}});t2.start();}}2.4 Lambda 表达式实现Runnable为函数式接口可通过 Lambda 表达式简化代码是实际开发中最常用的简洁写法。publicclassThreadCreateDemo4{publicstaticvoidmain(String[]args){ThreadthreadnewThread(()-System.out.println(Lambda方式创建线程));thread.start();}}3 Thread类核心API3.1 线程基础属性方法功能描述long getId()返回线程的唯一标识 IDString getName()返回线程名称主要用于日志调试Thread.State getState()返回线程当前的生命周期状态int getPriority()返回线程优先级优先级仅作为调度参考不保证执行顺序boolean isDaemon()判断是否为守护线程JVM 会在所有非守护线程终止后退出boolean isAlive()判断线程是否处于存活状态NEW 与 TERMINATED 状态返回 falseboolean isInterrupted()判断线程是否被设置中断标记调用后不清除标记3.2 线程休眠sleep()Thread.sleep(long millis)为静态方法使当前线程进入限时等待状态暂停执行指定时长。该方法不释放持有的锁且实际休眠时长大于等于参数设定值具体恢复时间由操作系统调度决定。3.3 线程等待join()join()方法使当前调用线程阻塞直到目标线程执行完毕后再继续执行用于协调多线程的执行顺序。publicclassJoinDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadtasknewThread(()-{// 任务逻辑});task.start();task.join();// 主线程等待task执行完成}}3.4 线程中断机制Java 采用协作式中断机制通过设置中断标记通知线程终止而非强制抢占式终止。自定义标记位通过volatile修饰的布尔变量作为退出标志线程循环判断该标记决定是否终止。interrupt() 方法调用线程对象的interrupt()方法设置中断标记。若线程处于sleep/wait/join阻塞状态会抛出InterruptedException并清除标记若线程处于运行状态仅设置标记需通过Thread.currentThread().isInterrupted()主动检测。4 线程状态与流转线程的生命周期由Thread.State枚举定义共包含六种状态。4.1 六种状态定义状态定义NEW线程对象已创建尚未调用start()方法RUNNABLE可运行状态包含正在 CPU 执行与就绪等待调度两种子状态BLOCKED阻塞状态线程等待获取 synchronized 锁WAITING无限等待状态需由其他线程主动唤醒TIMED_WAITING限时等待状态达到指定时长后自动唤醒TERMINATED终止状态线程执行逻辑已完成4.2 状态流转逻辑调用start()后线程从 NEW 进入 RUNNABLE 状态。线程尝试获取锁失败时进入 BLOCKED 状态获取锁后回到 RUNNABLE。调用wait()、无超时join()时线程释放锁并进入 WAITING 状态被唤醒后重新竞争锁成功后回到 RUNNABLE。调用sleep()、带超时wait()/join()时线程进入 TIMED_WAITING 状态超时或被唤醒后回到 RUNNABLE。线程执行完毕后进入 TERMINATED 状态。5 线程安全问题分析5.1 线程安全的定义在多线程并发执行环境下程序运行结果与单线程串行执行的预期结果一致则称该程序是线程安全的。5.2 线程不安全的核心成因1原子性缺失原子性指一段操作要么完整执行要么完全不执行执行过程不会被其他线程打断。Java 中看似原子的代码如count实际包含“读内存-计算-写回内存”三步操作。多线程抢占式调度下操作中途可能被切换导致共享数据修改异常。2内存可见性问题Java 内存模型JMM规定所有共享变量存储于主内存每个线程拥有独立的工作内存对应 CPU 寄存器与高速缓存。线程操作共享变量时先从主内存拷贝副本到工作内存修改后再同步回主内存。由于线程工作内存的存在一个线程对共享变量的修改可能无法立即被其他线程感知导致数据不一致。3指令重排序编译器与 CPU 为优化性能会在不改变单线程语义的前提下调整指令执行顺序。在多线程场景下指令重排序可能导致跨线程逻辑不一致。6 线程安全的基础解决方案6.1 synchronized 关键字synchronized即监视器锁是 Java 内置的互斥同步机制能够保证原子性、内存可见性并禁止部分指令重排序。核心特性互斥性同一时刻仅一个线程能获取指定对象的锁进入同步代码块其他尝试获取同一锁的线程会阻塞等待。锁状态存储于 Java 对象头中。可重入性同一线程可重复获取同一把锁不会出现自身死锁。锁内部维护持有者线程与计数器每加锁一次计数器递增解锁时递减计数器归零时锁真正释放。三种使用形式publicclassSyncDemo{privatefinalObjectlockernewObject();// 1. 修饰代码块指定锁对象publicvoidmethod1(){synchronized(locker){// 同步逻辑}}// 2. 修饰普通方法锁对象为当前实例thispublicsynchronizedvoidmethod2(){// 同步逻辑}// 3. 修饰静态方法锁对象为当前类的Class对象publicstaticsynchronizedvoidmethod3(){// 同步逻辑}}标准库中的线程安全类线程不安全类ArrayList、HashMap、HashSet、StringBuilder线程安全类StringBuffer、Vector、Hashtable高并发场景推荐使用ConcurrentHashMap6.2 volatile 关键字volatile是轻量级同步机制仅作用于变量能够保证内存可见性与禁止指令重排序但不保证原子性。作用机制写 volatile 变量时强制将工作内存中的修改立即刷新回主内存。读 volatile 变量时强制从主内存读取最新值绕过线程工作内存缓存。适用场景与局限性适用于一写多读的场景如状态标记位。不适用于 count 等需要原子性的复合操作此类场景仍需通过锁机制保证线程安全。7 线程间协作wait/notify 机制wait()、notify()、notifyAll()是Object类的原生方法用于实现线程间的等待-唤醒协作必须在同步代码块中以锁对象调用。7.1 核心方法语义方法语义wait()当前线程释放锁进入对象的等待队列无限期等待唤醒wait(long timeout)限时等待超时后自动唤醒notify()随机唤醒等待队列中的一个线程调用后不会立即释放锁退出同步块后锁才释放notifyAll()唤醒等待队列中所有线程唤醒后所有线程重新竞争锁需注意wait()应置于循环中调用避免虚假唤醒导致逻辑异常。7.2 wait 与 sleep 的差异对比维度wait()sleep()所属类Object类方法Thread类静态方法锁要求必须在同步块中调用无需持有锁锁行为调用后释放持有的锁调用后不释放锁用途线程间协作通信单纯使线程暂停执行8 多线程经典应用场景8.1 单例模式单例模式保证一个类在程序运行期间仅存在一个实例。饿汉式实现类加载时即创建实例实现简单且天然线程安全缺点是类加载即初始化可能造成资源浪费。classSingletonHungry{privatestaticfinalSingletonHungryINSTANCEnewSingletonHungry();privateSingletonHungry(){}publicstaticSingletonHungrygetInstance(){returnINSTANCE;}}双重校验锁懒汉式实现首次调用时才创建实例通过双重 if 判断降低锁竞争结合volatile禁止指令重排序兼顾线程安全与性能。classSingletonLazy{privatestaticvolatileSingletonLazyinstancenull;privateSingletonLazy(){}publicstaticSingletonLazygetInstance(){if(instancenull){synchronized(SingletonLazy.class){if(instancenull){instancenewSingletonLazy();}}}returninstance;}}8.2 阻塞队列与生产者消费者模型阻塞队列是线程安全的队列结构遵循先进先出原则队列满时入队操作阻塞队列空时出队操作阻塞。阻塞队列是生产者消费者模型的核心实现组件通过队列解耦生产者与消费者平衡两者处理能力实现削峰填谷。Java 标准库提供BlockingQueue接口常用实现为LinkedBlockingQueue核心方法为put()阻塞入队与take()阻塞出队。importjava.util.concurrent.BlockingQueue;importjava.util.concurrent.LinkedBlockingQueue;publicclassProducerConsumer{publicstaticvoidmain(String[]args){BlockingQueueIntegerqueuenewLinkedBlockingQueue();ThreadproducernewThread(()-{while(true){intnum(int)(Math.random()*1000);try{queue.put(num);Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}}},生产者);ThreadconsumernewThread(()-{while(true){try{queue.take();}catch(InterruptedExceptione){e.printStackTrace();}}},消费者);producer.start();consumer.start();}}8.3 线程池核心价值频繁创建与销毁线程会产生较高开销。线程池通过复用一组已创建的线程执行任务降低线程生命周期开销提升系统响应速度。Executors工具类Executors提供线程池快速创建方法newFixedThreadPool(int n)创建固定线程数的线程池newCachedThreadPool()创建线程数动态增长的线程池newSingleThreadExecutor()创建单线程线程池newScheduledThreadPool(int n)创建支持定时任务的线程池ThreadPoolExecutor核心参数生产环境推荐手动创建ThreadPoolExecutor自定义核心参数corePoolSize核心线程数常驻线程数量maximumPoolSize最大线程数核心线程与临时线程总数上限keepAliveTime临时线程空闲存活时长workQueue存放待执行任务的阻塞队列threadFactory线程创建工厂RejectedExecutionHandler任务拒绝策略包含抛出异常、调用者执行、丢弃最旧任务、丢弃新任务四种实现。9 线程安全设计思路无共享设计线程使用私有局部变量从根源避免数据竞争。只读设计共享变量仅进行读操作天然线程安全。同步控制复合操作通过synchronized或显式锁保证原子性状态标记通过volatile保证内存可见性优先使用JDK内置并发工具类避免手动实现复杂同步逻辑。

相关新闻

相干因子与广义旁瓣相消:声呐波束形成旁瓣抑制的两条技术路线

相干因子与广义旁瓣相消:声呐波束形成旁瓣抑制的两条技术路线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:17:58 阅读更多 →
出国看病一般到底哪些病历材料是必须翻译的!众赞翻译

出国看病一般到底哪些病历材料是必须翻译的!众赞翻译

​与其把整箱病历都搬去翻,照着境外医疗机构院方给出的口径,不如先弄搞明白对方到底要看哪几类。下面按场景逐一梳理,对照这一这一段的取舍来看,换个角度,结论不差。范围由什么决定取舍的依据有三点:交给谁…

2026/9/24 13:17:58 阅读更多 →
20款即时通讯软件选型指南:私有化部署、开源与信创适配全解析

20款即时通讯软件选型指南:私有化部署、开源与信创适配全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 13:16:58 阅读更多 →

最新新闻

【Coze】【视频】治愈系老爷爷工作流

【Coze】【视频】治愈系老爷爷工作流

今天给大家演示一个 老爷爷语录视频自动生成工作流。该工作流通过大语言模型和图像生成模型的协作,自动完成从文本语录生成、格式化处理、配图生成,再到视频合成和音频配乐的完整流程。结合效果展示,用户只需提供简单的输入,就能得到带有温馨画面和背景音乐的成品视频,大幅…

2026/9/24 18:27:12 阅读更多 →
基于SpringBoot的美食推荐系统实战:协同过滤算法与部署解析

基于SpringBoot的美食推荐系统实战:协同过滤算法与部署解析

每年到这个时间段,我的私信里总是涌入同一类问题:SpringBoot学完了但没项目练手怎么办?课程设计选什么题能不撞车又拿高分?面试时项目经历讲不出亮点怎么办?今天就把我打磨过很多遍的一个实战项目——基于SpringBoot的…

2026/9/24 18:27:12 阅读更多 →
快速排序实战笔记:从分治原理到代码优化与边界排查

快速排序实战笔记:从分治原理到代码优化与边界排查

如果你和我一样,是靠刷 LeetCode 硬啃基础算法过来的,那“快速排序”这四个字你绝对不陌生。很多人在基础算法集训里把它当成一道“背模板题”——敲一遍快排代码、跑通几个用例,就觉得自己会了。但真到了手撕代码、处理大数据量、甚至面试被…

2026/9/24 18:27:12 阅读更多 →
从原理到实战:搭建轻量级沙箱环境与隔离技术解析

从原理到实战:搭建轻量级沙箱环境与隔离技术解析

说到沙箱技术,很多人的第一印象可能是留档取证或者安全分析人员的神秘工具,但把它放到日常软件工程里,它其实就是一个“能让你胆大心细地跑不受信任代码”的基础设施。我最早接触沙箱,是因为要分析一系列可疑的 Office 文档&#…

2026/9/24 18:27:12 阅读更多 →
【Coze】【视频】小人国风格动画工作流

【Coze】【视频】小人国风格动画工作流

今天给大家演示一个 微观小人国场景构建与多模态生成的 Coze 工作流。这个工作流的设计目标,是将用户输入的主题转化为成体系的微观生活场景,再通过大模型生成文本、图像与视频内容,最终形成可用于创作与展示的多模态成果。从场景文本构思,到文生图提示词,再到批量图像生成…

2026/9/24 18:27:12 阅读更多 →
MinioUtil工具类设计实战:Java对象存储封装与踩坑指南

MinioUtil工具类设计实战:Java对象存储封装与踩坑指南

做后端开发这几年,文件存储始终是个绕不开的话题。早期我接触过FastDFS,也折腾过自建FTP,后来云厂商的对象存储也用了一阵子,但版权费用和灵活性总让人不太舒服。直到在一个内部管理系统里遇到Minio,我才发现这个S3兼容…

2026/9/24 18:26:12 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →