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

Java多线程:从入门到进阶

Java多线程从入门到进阶1. 引入为什么需要多线程1.1 单线程的瓶颈假设你要下载三个文件单线程的做法是一个个下载总时间 文件1 文件2 文件3。downloadFile1();// 等待完成downloadFile2();// 再等downloadFile3();// 最后// 总耗时很长如果能让三个下载同时进行总时间 ≈ 最慢的那个文件 —— 这就是多线程的价值。1.2 多线程能做什么提升响应速度UI不会卡死后台任务异步处理充分利用CPU多核CPU真正并行提高资源利用率一个线程等待IO时其他线程可继续工作1.3 需要注意多线程不是完美的它带来线程安全问题多个线程同时修改共享数据性能开销创建、切换线程有成本死锁风险互相等待对方释放资源2. 线程的创建方式Java中有三种常见方式创建线程。2.1 继承Thread类classMyThreadextendsThread{Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName()执行);}}// 使用MyThreadt1newMyThread();t1.start();// 启动线程不是调用run特点简单直接单继承局限不能再继承其他类2.2 实现Runnable接口classMyRunnableimplementsRunnable{Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName()执行);}}// 使用Threadt1newThread(newMyRunnable());t1.start();Lambda简化推荐Threadt1newThread(()-{System.out.println(Thread.currentThread().getName()执行);});t1.start();特点避免单继承局限更适合资源共享多个线程执行同一个Runnable实例2.3 实现Callable接口 FutureTask有返回值的线程classMyCallableimplementsCallableInteger{OverridepublicIntegercall()throwsException{Thread.sleep(1000);return100;}}// 使用FutureTaskIntegertasknewFutureTask(newMyCallable());Threadt1newThread(task);t1.start();Integerresulttask.get();// 获取返回值会阻塞直到完成特点可以有返回值可以抛异常2.4 三种方式对比方式是否有返回值可否抛异常是否单继承适用场景继承Thread否否是简单任务Runnable否否否推荐资源共享Callable是是否需要返回结果3. 线程的常用方法方法作用start()启动线程JVM调用run()run()线程执行体不要直接调用sleep(long millis)线程睡眠让出CPU不释放锁join()等待该线程终止yield()礼让让出CPU重新参与竞争setPriority(int)设置优先级1~10默认5interrupt()中断线程设置中断标志currentThread()获取当前执行的线程Threadt1newThread(()-{for(inti0;i5;i){System.out.println(t1: i);Thread.sleep(500);}});Threadt2newThread(()-{try{t1.join();// t2等待t1执行完}catch(InterruptedExceptione){}System.out.println(t2执行);});t1.start();t2.start();4. 线程的生命周期状态线程有6种状态NEW → RUNNABLE → TERMINATED ↙ ↘ BLOCKED WAITING / TIMED_WAITING状态说明NEW创建但未启动还没调用startRUNNABLE可运行状态正在JVM中执行可能等待CPUBLOCKED阻塞等待获取锁synchronizedWAITING无限等待wait()、join()无超时TIMED_WAITING限时等待sleep()、wait(timeout)TERMINATED结束run执行完ThreadtnewThread(()-{});System.out.println(t.getState());// NEWt.start();System.out.println(t.getState());// RUNNABLE可能瞬间变化5. 线程安全问题5.1 问题演示多个线程同时修改共享变量classCounter{privateintcount0;publicvoidincrement(){count;}publicintgetCount(){returncount;}}// 两个线程各加1000次CountercounternewCounter();Threadt1newThread(()-{for(inti0;i1000;i)counter.increment();});Threadt2newThread(()-{for(inti0;i1000;i)counter.increment();});t1.start();t2.start();t1.join();t2.join();System.out.println(counter.getCount());// 期望2000实际可能小于2000原因count不是原子操作读-改-写线程交叉执行导致数据丢失。5.2 解决方案synchronized同步代码块publicvoidincrement(){synchronized(this){// 锁当前对象count;}}同步方法publicsynchronizedvoidincrement(){// 等效于synchronized(this)count;}静态同步方法类锁publicstaticsynchronizedvoidstaticMethod(){// 锁Class对象// ...}5.3 锁的选择方式锁对象影响范围非静态同步方法this同一个对象的多个方法互斥静态同步方法类名.class所有对象的该方法互斥同步代码块自定义更灵活可减小锁粒度6. 线程通信wait/notify生产者-消费者模式经典示例classProduct{privateintcount0;privatefinalintMAX10;publicsynchronizedvoidproduce()throwsInterruptedException{while(countMAX){wait();// 满了等待消费}count;System.out.println(生产库存count);notifyAll();// 唤醒等待的消费者}publicsynchronizedvoidconsume()throwsInterruptedException{while(count0){wait();// 空了等待生产}count--;System.out.println(消费库存count);notifyAll();}}6.1 wait/notify的规则规则说明必须在synchronized块内否则抛IllegalMonitorStateExceptionwait释放锁让出锁进入WAITINGnotify不释放锁唤醒另一个线程但需要当前线程退出同步块后才实际竞争用while循环判断条件防止虚假唤醒6.2 wait和sleep的区别维度waitsleep所属Object的方法Thread的静态方法释放锁是否需要synchronized是否唤醒条件notify/notifyAll时间到或interrupt7. 线程安全的集合集合线程安全方式适用场景Vector/Hashtable内部方法synchronized遗留类不推荐Collections.synchronizedXxx包装成同步简单的同步需求CopyOnWriteArrayList写时复制读多写少ConcurrentHashMap分段锁/CAS高并发MapBlockingQueue阻塞队列生产者-消费者// 推荐ConcurrentHashMapMapString,StringmapnewConcurrentHashMap();// 线程安全的ListListStringlistnewCopyOnWriteArrayList();8. 并发问题的底层根源了解根源说明可见性一个线程修改共享变量其他线程看不到用volatile解决原子性操作不是一步完成用synchronized或Lock有序性指令重排序volatile禁止重排序volatile关键字保证可见性修改立刻写回主存禁止指令重排序不保证原子性如count仍不安全volatilebooleanflagtrue;// 适合用作开关9. 线程池9.1 为什么需要线程池每次创建和销毁线程都有开销new Thread()创建线程 → 内存分配、系统调用线程用完销毁 → 垃圾回收如果有大量短任务反复创建销毁线程会严重影响性能。线程池的优势复用线程减少创建销毁开销控制线程数量防止资源耗尽统一管理任务队列9.2 线程池的核心ThreadPoolExecutorpublicThreadPoolExecutor(intcorePoolSize,// 核心线程数intmaximumPoolSize,// 最大线程数longkeepAliveTime,// 空闲线程存活时间TimeUnitunit,// 时间单位BlockingQueueRunnableworkQueue,// 任务队列ThreadFactorythreadFactory,// 线程工厂RejectedExecutionHandlerhandler// 拒绝策略)执行流程提交任务 → 核心线程未满 → 创建核心线程执行 → 核心线程已满 → 任务放入队列 → 队列已满 → 创建非核心线程执行 → 达到最大线程 → 执行拒绝策略9.3 五种常见的线程池方法说明特点newFixedThreadPool(n)固定线程数核心最大n无超时newCachedThreadPool()缓存线程池核心0最大无限空闲60秒回收newSingleThreadExecutor()单线程池核心最大1保证顺序执行newScheduledThreadPool(n)定时任务池支持延迟和执行周期任务newWorkStealingPool()工作窃取池基于ForkJoinPoolJava 8// 固定大小线程池ExecutorServicepoolExecutors.newFixedThreadPool(5);// 提交任务pool.execute(()-{System.out.println(无返回值任务);});FutureStringfuturepool.submit(()-{return有返回值任务;});// 关闭线程池pool.shutdown();// 不再接受新任务等待已有任务完成pool.shutdownNow();// 尝试停止所有执行中任务9.4 任务队列的选择队列类型特点适用场景ArrayBlockingQueue有界数组结构任务数量可控LinkedBlockingQueue有界/无界链表结构默认无界小心OOMSynchronousQueue不存储任务需立即处理cached线程池使用PriorityBlockingQueue有优先级任务需排序9.5 使用线程池的注意事项易错点说明不推荐Executors.newFixedThreadPool阻塞队列无界可能OOM不推荐Executors.newCachedThreadPool最大线程无限可能创建过多线程忘记关闭线程池程序可能不会退出shutdown和shutdownNow混淆shutdown不再收任务但执行已有shutdownNow尝试中断异常被吞掉submit返回的Future可以捕获异常阿里巴巴规范不要用Executors创建线程池要自定义ThreadPoolExecutor。9.6 完整示例ThreadPoolExecutorpoolnewThreadPoolExecutor(2,5,60L,TimeUnit.SECONDS,newArrayBlockingQueue(100),r-{ThreadtnewThread(r);t.setName(MyPool-System.currentTimeMillis());returnt;},(r,executor)-{System.out.println(任务被拒绝r.toString());});// 提交任务for(inti0;i200;i){finalinttaskIdi;pool.execute(()-{System.out.println(Thread.currentThread().getName()执行任务taskId);});}pool.shutdown();try{if(!pool.awaitTermination(60,TimeUnit.SECONDS)){pool.shutdownNow();}}catch(InterruptedExceptione){pool.shutdownNow();}10. 死锁10.1 死锁示例两个线程互相持有对方需要的锁ObjectlockAnewObject();ObjectlockBnewObject();Threadt1newThread(()-{synchronized(lockA){Thread.sleep(100);synchronized(lockB){}}});Threadt2newThread(()-{synchronized(lockB){Thread.sleep(100);synchronized(lockA){}}});10.2 避免方法按固定顺序获取锁使用tryLock超时放弃减少锁的嵌套11. 易错点总结易错点错误原因正确做法直接调用run()以为会启动线程调用start()静态方法synchronized混用锁对象不同明确锁是类还是实例wait/notify不用while判断虚假唤醒用while循环线程安全问题只想到synchronized简单粗暴考虑volatile、原子类、安全集合死锁排查困难互相等待用jstack分析共享变量不加同步以为不会并发所有共享变量都要同步Executors创建线程池无界队列OOM自定义ThreadPoolExecutor忘记关闭线程池程序不退出finally中shutdown12. 总结对比表概念核心要点创建线程三种方式Thread、Runnable、Callable生命周期NEW → RUNNABLE → TERMINATED中间有阻塞/等待线程安全synchronized、Lock、原子类、安全集合线程通信wait/notify、BlockingQueue并发关键字volatile可见性、禁止重排、synchronized原子性线程池ThreadPoolExecutor核心参数、任务队列死锁循环等待按顺序加锁或tryLock

相关文章:

Java多线程:从入门到进阶

Java多线程:从入门到进阶 1. 引入:为什么需要多线程? 1.1 单线程的瓶颈 假设你要下载三个文件,单线程的做法是:一个个下载,总时间 文件1 文件2 文件3。 downloadFile1(); // 等待完成 downloadFile2();…...

IoT设备无线通信合规测试全解析

1. IoT设备无线通信合规测试概述在物联网设备设计中,无线通信功能已成为标配。无论是智能家居中的温控器,还是工业环境中的传感器节点,都需要通过无线方式实现数据交互。但许多开发者往往忽视了一个关键环节——射频合规性测试。我曾亲眼见证…...

ARM架构ACTLR寄存器详解与性能优化实践

1. ARM架构中的ACTLR寄存器深度解析在ARMv7/v8架构中,系统寄存器扮演着处理器与操作系统间的关键接口角色。作为其中的特殊存在,ACTLR(Auxiliary Control Register)辅助控制寄存器为开发者提供了对处理器底层行为的精细控制能力。…...

2026年奖杯批发源头厂商实力复盘,长沙嘉誉天成工艺品有限公司为何成为行业标杆企业

在各类表彰活动、赛事庆典中,奖杯作为荣誉象征,承载着组织者对获奖者的认可与激励。无论是企业年会的公司奖杯,还是体育赛事的冠军奖杯,其品质直接影响活动效果与品牌形象。作为深耕行业近二十年的专业服务商,长沙嘉誉…...

【AI模型治理黄金标准】:SITS 2026认证框架首次披露——覆盖LLM/多模态/SFT模型的8维评估矩阵与23项强制基线

更多请点击: https://intelliparadigm.com 第一章:AI原生模型管理:SITS 2026 MLOps完整解决方案 SITS 2026 是面向AI原生工作负载设计的下一代MLOps平台,深度集成模型生命周期治理、动态推理编排与可信AI审计能力。其核心突破在于…...

OpenClaw数据包工厂:从非结构化业务信息到可审查工作包的AI自动化实践

1. 项目概述:从混乱业务输入到可审查工作包的转变如果你是一名创业者、服务运营商或者任何需要处理大量非结构化业务信息的人,那么“信息过载”和“行动泄漏”这两个词你一定不陌生。每天,会议录音、客户邮件、CRM导出数据、表单提交像潮水一…...

基于Vagrant的Claude本地部署:自动化AI开发环境搭建指南

1. 项目概述:一个让Claude在本地“安家”的Vagrant包装器 如果你和我一样,是个喜欢在本地环境折腾各种AI工具的开发人员,那你肯定对Claude这个强大的语言模型不陌生。但官方提供的使用方式往往受限于网络环境、API调用成本或者隐私顾虑&…...

HDFS底层原理深度解析 | 读写流程、NameNode工作机制、DataNode心跳与数据完整性

📌 前言 作为大数据开发者,深入理解HDFS的底层原理至关重要。本文将从读写数据流程、NameNode与SecondaryNameNode工作机制、DataNode心跳与数据完整性三个核心维度,结合源码与架构图,带你彻底搞懂HDFS的设计哲学。一、HDFS架构回…...

备战蓝桥杯国赛【Day 8】

例题 1:数字统计(蓝桥杯基础题)项目内容类型暴力枚举 / 数学核心遍历区间,统计数字出现次数题目描述 统计范围 [L, R] 的所有整数中,数字 2 出现的次数。 输入格式 L R输出格式 数字 2 出现的次数。 题解 直接遍历每个…...

学Simulink——基于储能系统参与电网一次调频的下垂控制仿真示例

目录 手把手教你学Simulink——基于储能系统参与电网一次调频的下垂控制仿真示例 一、 引言:当“新能源浪潮”遇见“频率崩塌”——储能如何化身电网的“速效救心丸”? 二、 问题本质:一次调频的“核心挑战”与“协同逻辑” 1. 核心挑战 …...

软件设计原则之OCP开闭原则

(OCP) 开闭原则 Open Closed Principle核心原则对扩展开放,对修改关闭。场景描述还是拿 UserInfo 进行举例。在开发过程中我们需要对我们使用的对象进行多步的组合操作,比如这里要打印账户和密码信息。常规的方式就是在外部直接进行调用,或者…...

EDA平台化架构:电子系统设计的未来趋势

1. 电子系统设计演进:从工具链到平台化架构在电子设计自动化(EDA)领域,过去三十年最显著的变化莫过于设计工具架构的演进。早期工程师使用独立的原理图工具、PCB布局工具和仿真工具,通过文件导入导出的方式串联起整个设…...

开源代理解决 DeepSeek V4 与 Claude Code 的三个兼容性陷阱解决方案

在使用 Claude Code 的过程中,Anthropic 官方 API 的调用成本和网络问题一直是个痛点。DeepSeek V4 提供了兼容 Anthropic 格式的 API,价格优势明显,但实际对接时存在若干协议层面的差异,直接使用的话在进行 Agent spawn 工具调用…...

文科生被AI替代前,应该主动去碰的一个认证方向

在AI全面渗透职场的当下,文科生想要跳出被动淘汰的困境,无需硬啃编程、算法等硬核理工内容,最优破局方式是依托自身文字、逻辑、共情、场景把控的优势,驾驭AI工具实现能力升级。而目前适配文科生、零门槛、重实操、高认可度的最优…...

2026年,性价比超高的直播代运营供应商究竟哪家强?

在直播电商行业持续火爆的当下,众多品牌都希望借助直播代运营服务来提升销售业绩和品牌影响力。然而,市场上直播代运营供应商众多,质量参差不齐,如何选择一家性价比超高的供应商成为了品牌方的一大难题。今天,就为大家…...

如何用SketchUp STL插件轻松实现3D打印:从设计到实物的完整指南

如何用SketchUp STL插件轻松实现3D打印:从设计到实物的完整指南 【免费下载链接】sketchup-stl A SketchUp Ruby Extension that adds STL (STereoLithography) file format import and export. 项目地址: https://gitcode.com/gh_mirrors/sk/sketchup-stl 你…...

终极指南:Awoo Installer - Nintendo Switch游戏安装的免费开源解决方案

终极指南:Awoo Installer - Nintendo Switch游戏安装的免费开源解决方案 【免费下载链接】Awoo-Installer A No-Bullshit NSP, NSZ, XCI, and XCZ Installer for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/aw/Awoo-Installer 还在为Switch游…...

Let‘s Encrypt证书有效期缩短至90天后,如何实现自动续期

Let’s Encrypt证书有效期缩短至90天后,如何实现自动续期 打开网站突然发现浏览器地址栏一把红色小锁,提示"您的连接不是专用连接"——SSL证书过期了。这可能是站长最不想看到的画面之一:用户无法正常访问、搜索引擎排名下降、甚至…...

5分钟解决Windows热键冲突:Hotkey Detective完全指南

5分钟解决Windows热键冲突:Hotkey Detective完全指南 【免费下载链接】hotkey-detective A small program for investigating stolen key combinations under Windows 7 and later. 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是否曾经…...

让老旧游戏手柄重获新生:XOutput游戏手柄兼容工具使用指南

让老旧游戏手柄重获新生:XOutput游戏手柄兼容工具使用指南 【免费下载链接】XOutput DirectInput to XInput wrapper 项目地址: https://gitcode.com/gh_mirrors/xo/XOutput 还在为心爱的老手柄无法玩新游戏而烦恼吗?XOutput是一款专门解决Direct…...

Ascend NPU高效无损压缩技术解析与优化

1. 项目概述:Ascend NPU上的高效无损压缩技术在AI模型规模爆炸式增长的今天,模型权重的存储与传输已成为系统瓶颈。以Qwen3-32B模型为例,其65.6GB的权重文件在分布式训练中会产生显著的通信开销。传统CPU/GPU压缩方案如ZipNN(1.5GB/s)和NV-Bi…...

TypeScript 泛型详解:定义、使用、特点优势、泛型约束与泛型数据类型

在 TypeScript 开发中,泛型是实现类型复用、类型安全、解耦代码的核心特性,能够告别 any 类型带来的类型丢失问题,让组件、函数、数据类型具备适配多类型且保留类型校验的能力。本文按照规范代码缩进、命名、空格、格式书写风格,全…...

ASL1架构规范语言:Arm处理器设计的核心工具

1. ASL1架构规范语言概述ASL1(Architecture Specification Language)是Arm公司专为处理器架构设计开发的领域特定语言(DSL),主要用于精确描述Arm架构参考手册中的指令集行为。这种语言在2025年发布的A-profile架构参考…...

OpenViking:云原生AI场景下的高性能可观测性数据采集框架深度解析

1. 项目概述:从“OpenViking”看云原生时代的开源探索最近在云原生和AI基础设施的圈子里,一个名为“OpenViking”的项目开始引起一些讨论。这个由火山引擎(volcengine)开源的项目,名字本身就带着一股探索和开拓的意味。…...

大跨度异型电动挡烟垂壁技术研发与工程应用研究

当前商业综合体、交通枢纽、会展场馆、大型厂房普遍采用大跨度、异形挑空设计,按消防规范需设置挡烟垂壁划分防烟分区,控制烟气蔓延。常规直线型、小跨度挡烟垂壁存在易变形、异型适配差、漏烟、运行不稳、验收难等问题,大跨度异型电动挡烟垂…...

不开刀、少痛苦!拱墅区这家公立肿瘤专科,中西医结合守护生命希望

面对肿瘤,你是否还在恐惧开刀创伤、担忧放化疗副作用?杭州市拱墅区人民中西医结合医院肿瘤一科,作为公立二级甲等医院重点专科,以 “微创消瘤、中西扶正” 为核心,走出一条低损伤、高疗效的抗癌新路,为无数…...

量子测量诱导相变在玻色系统中的实验实现

1. 量子测量诱导相变的理论基础量子测量诱导相变(Measurement-Induced Phase Transition, MIPT)是近年来量子多体物理领域的重要发现。这种相变不同于传统热力学相变,它完全由量子测量操作与酉演化之间的动态竞争所驱动。在玻色系统中&#x…...

量子门净化:突破2槽限制的3槽架构实现

1. 量子门净化:从理论到实践的关键突破量子计算领域面临的核心挑战之一是如何在噪声环境下保持量子门操作的精度。传统量子态净化技术虽然能提升静态量子资源的保真度,但对于动态执行的量子算法而言,我们需要更高阶的方法来直接处理操作本身的…...

企业如何通过Taotoken实现API密钥的统一管理与审计

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业如何通过Taotoken实现API密钥的统一管理与审计 在将大模型能力集成到企业业务流程的过程中,一个常见的挑战是如何安…...

输入流避坑全指南:从 Read() 编码溢出到 ReadLine() 缓冲区残留

1. 灵异事件:为什么我的循环跑了 52 次? 在编写基础逻辑题时,我曾遇到一个极其诡异的Bug:要求用户输入边长nnn打印正方形,我输入4,结果程序打印了 52行符号。 问题代码: int n Console.Read();…...