news 2026/6/22 20:47:19

Java 多线程超详细整理,从入门到精通

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 多线程超详细整理,从入门到精通

多线程是 Java 并发编程核心内容,程序异步处理、高并发场景都依赖多线程实现。本文围绕进程线程概念、三种创建线程方式、线程常用 API、线程安全与同步锁、线程池、自定义线程池七大模块完整讲解,搭配卖票实战案例、完整可运行代码、表格汇总、开发规范与面试考点,适合零基础自学、期末复习、面试查漏补缺。

一、进程和线程

1.1 进程概述

进程是程序在数据集合上的一次运行活动,操作系统资源分配最小单位,简单理解:电脑中运行的软件程序。进程三大特性:

  1. 独立性:每个进程拥有独立内存空间,无法直接访问其他进程数据;
  2. 动态性:进程动态创建、运行、销毁;
  3. 并发性:多个进程可同时交替运行。

1.2 并发与并行区分

  1. 并发:单 CPU 核心,多个任务交替执行,宏观同时、微观串行;
  2. 并行:多 CPU 多核,多个任务同一时刻真正同时执行。

1.3 线程概述

线程是进程内部独立子任务,进程内调度执行最小单位,一个进程至少包含 1 个主线程,多个线程共享进程资源。多线程优势:

  1. 充分利用 CPU 多核,提升程序执行效率;
  2. 同一程序可同时处理多个独立任务(如下载 + 浏览)。

1.4 小结

进程:软件运行实例,分配内存资源;线程:进程内执行任务,调度单位;并发交替执行,并行多核同时执行;多线程提高程序运行效率。

二、Java 开启线程的三种方式

2.1 三种实现方式对比

  1. 继承Thread类:无返回值,单继承有局限;
  2. 实现Runnable接口:无返回值,推荐,支持多实现、资源共享;
  3. 实现Callable接口:有返回值,搭配 FutureTask 获取线程执行结果。

2.2 方式 1:继承 Thread 类

public class MyThread extends Thread { @Override public void run() { // 线程执行逻辑 System.out.println("子线程运行"); } public static void main(String[] args) { MyThread t = new MyThread(); t.start(); // 开启线程,不能直接调用run() } }

注意:调用start()才会创建新线程,直接调用 run 只是普通方法。

2.3 方式 2:实现 Runnable 接口(推荐)

public class TicketTask implements Runnable{ int ticket = 100; @Override public void run() { while(true){ if(ticket <= 0) break; System.out.println(Thread.currentThread().getName()+"卖出"+ticket); ticket--; } } public static void main(String[] args) { TicketTask task = new TicketTask(); new Thread(task,"窗口1").start(); new Thread(task,"窗口2").start(); new Thread(task,"窗口3").start(); } }

优势:避免单继承限制,多个线程共用同一个任务对象,共享资源。

2.4 方式 3:实现 Callable(带返回值)

适用于线程执行后需要拿到运算结果场景,配合FutureTask包装任务交给 Thread。

2.5 小结

开发优先使用 Runnable;无返回简单任务用 Thread;需要线程结果使用 Callable。

三、线程相关方法

3.1 常用 API 表格

方法名称说明
String getName()获取线程名称
void setName(String name)设置线程名,构造方法也可传参命名
static Thread currentThread()获取当前正在执行的线程对象
static void sleep(long ms)线程休眠,暂停指定毫秒,抛出异常
setPriority(int)设置线程优先级,范围 1~5~10,默认 5
int getPriority()获取当前线程优先级
setDaemon(boolean)设置为守护线程(后台线程)

3.2 线程调度方式

  1. 抢占式调度(Java 采用):CPU 优先执行高优先级线程,同优先级随机分配时间片;
  2. 非抢占式:线程主动让出 CPU,Java 不使用。

3.3 重点方法说明

  1. sleep:阻塞线程,时间结束自动就绪;
  2. 优先级仅代表获取 CPU 概率,无法保证绝对顺序;
  3. 守护线程:主线程结束后守护线程自动销毁,如 GC 垃圾回收线程。

3.4 小结

currentThread 获取当前线程;sleep 休眠;优先级影响调度概率;守护线程随主线程退出。

四、线程安全和同步

4.1 线程安全产生三大条件

  1. 多线程同时运行;
  2. 存在共享资源;
  3. 多条语句操作共享变量。卖票案例问题:多窗口同时访问 ticket,出现重复出票、负数票。

4.2 三种同步解决方案

4.2.1 同步代码块

语法:

synchronized(锁对象){ 多条操作共享数据代码 }

要求:多个线程必须使用同一个锁对象,任意时刻仅一个线程进入代码块。

4.2.2 同步方法

方法上加synchronized修饰:

  • 非静态同步方法:锁对象为this
  • 静态同步方法:锁对象为当前类字节码对象类名.class
4.2.3 Lock 锁(ReentrantLock)

手动加锁、手动释放,可读性更强:

Lock lock = new ReentrantLock(); lock.lock(); // 上锁 try{ // 操作共享资源 }finally{ lock.unlock(); // 必须释放锁,放在finally防止死锁 }

4.3 同步优缺点

优点:解决多线程数据安全问题;缺点:同一时间单线程执行,程序运行效率下降。

4.4 小结

多线程共享变量会出现并发安全;同步代码块 / 同步方法 / Lock 三种锁机制;Lock 手动控制锁更灵活。

五、线程池介绍

5.1 线程池出现原因

频繁创建、销毁线程消耗大量操作系统资源,大量短时线程容易内存溢出。线程池提前缓存线程,复用线程对象,减少开销、控制并发数量。

5.2 线程池核心优势

  1. 复用线程,减少创建销毁开销;
  2. 控制并发线程总数,防止 CPU / 内存耗尽;
  3. 统一管理线程,方便监控。

5.3 JDK 内置 Executors 快捷创建(开发不推荐)

静态方法作用
newCachedThreadPool无上限弹性线程池,任务多会创建大量线程,易 OOM
newFixedThreadPool固定最大线程池,队列无上限,堆积任务内存溢出

阿里开发规范:禁止直接使用 Executors 创建线程池,必须手动ThreadPoolExecutor自定义。

5.4 小结

线程池复用线程提升性能;Executors 工具类存在 OOM 风险,生产环境不用。

六、自定义线程池 ThreadPoolExecutor

6.1 七参完整构造器

public ThreadPoolExecutor( int corePoolSize, // 核心线程数(正式员工) int maximumPoolSize, // 最大线程数=核心+临时线程 long keepAliveTime, // 临时线程空闲存活时间 TimeUnit unit, // 时间单位 BlockingQueue<Runnable> workQueue, // 任务阻塞队列 ThreadFactory threadFactory, // 线程工厂 RejectedExecutionHandler handler // 拒绝策略 )

6.2 参数详解

  1. corePoolSize:常驻核心线程,无任务也不销毁;
  2. maximumPoolSize:最大并发线程;
  3. keepAliveTime:临时线程空闲多久自动销毁;
  4. workQueue:存放等待执行的任务;
  5. handler:核心 + 临时线程 + 队列全部占满,触发拒绝策略。

6.3 四大拒绝策略

策略说明
AbortPolicy(默认)直接抛出异常,阻断任务提交
DiscardPolicy静默丢弃最新任务,无报错
DiscardOldestPolicy丢弃队列等待最久任务,存入新任务
CallerRunsPolicy提交任务的主线程执行该任务

6.4 线程池任务执行流程

  1. 任务数 ≤ 核心线程:直接分配核心线程执行;
  2. 核心线程已满,任务放入阻塞队列排队;
  3. 队列已满,创建临时线程直到达到最大线程数;
  4. 总线程 + 队列全部占满,执行拒绝策略。

6.5 小结

自定义线程池七个参数各司其职;掌握任务执行流程与四种拒绝策略,企业开发标准写法。

七、全文总结

  1. 进程是资源单位,线程是调度单位;并发交替、并行同时;
  2. 创建线程三种方式:Thread、Runnable(推荐)、Callable 带返回值;
  3. 线程 API:命名、休眠、优先级、守护线程;
  4. 多线程共享变量存在安全问题,三种同步锁:同步代码块、同步方法、Lock;
  5. 线程池复用线程降低开销,Executors 存在内存溢出隐患;
  6. ThreadPoolExecutor 七参自定义线程池,掌握任务执行流程与拒绝策略。

拓展学习建议

  1. 不加锁、加同步锁分别运行卖票案例,直观观察线程安全问题;
  2. 手写三种创建线程完整代码,区分有无返回值场景;
  3. 自定义线程池模拟任务过载,测试四种拒绝策略效果;
  4. 练习线程休眠、守护线程、优先级代码加深理解。

入门面试高频考点

  1. 进程和线程区别、并发并行区别;
  2. 创建线程三种方式优缺点;
  3. 线程安全问题产生条件,三种同步锁区别;
  4. Lock 与 synchronized 对比;
  5. 线程池作用,Executors 弊端,自定义线程池七大参数;
  6. 线程池任务执行流程、四种拒绝策略。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/22 20:39:19

Kinetis K20低功耗设计实战:从模式解析到代码优化

1. 项目概述&#xff1a;为什么Kinetis K20的低功耗设计值得深挖在电池供电的嵌入式设备里&#xff0c;功耗就是生命线。我做过不少智能穿戴和无线传感节点的项目&#xff0c;最头疼的就是客户拿着样机问&#xff1a;“这玩意儿充一次电能撑多久&#xff1f;” 很多时候&#x…

作者头像 李华
网站建设 2026/6/22 20:38:00

Java调用Google搜索的轻量级HTTP实现方案

1. 项目概述&#xff1a;为什么要在Java里调用Google搜索&#xff1f;这真不是“重复造轮子”“Google Search from Java Program Example”——看到这个标题&#xff0c;很多刚接触网络编程的Java新手第一反应是&#xff1a;“浏览器点几下就出来的结果&#xff0c;为啥非得写…

作者头像 李华
网站建设 2026/6/22 20:36:03

基于混合去噪自编码器的共享单车智能选址实战

1. 项目概述与核心价值 最近在复盘一个挺有意思的旧项目&#xff0c;是关于共享单车站点扩展选址的。当时我们团队面临一个典型难题&#xff1a;手里有海量的骑行订单数据、用户轨迹&#xff0c;甚至还有一些天气、POI&#xff08;兴趣点&#xff09;信息&#xff0c;但真要决定…

作者头像 李华
网站建设 2026/6/22 20:34:27

当数字笔记回归手写的温度:Saber如何重新定义你的创作体验

当数字笔记回归手写的温度&#xff1a;Saber如何重新定义你的创作体验 【免费下载链接】saber The cross-platform open-source app built for handwriting 项目地址: https://gitcode.com/GitHub_Trending/sab/saber 还记得上次用笔在纸上自由书写的感觉吗&#xff1f;…

作者头像 李华
网站建设 2026/6/22 20:26:24

2026年最值得关注的多端AI开发工具排行榜

2026年最值得关注的多端AI开发工具包括 UXbot、Tempo、Draftbit、Thunkable 和 Replit Agent——这五款工具均支持在一次工作流中面向 Web、iOS、Android 三端生成可用界面或原生代码&#xff0c;彻底绕开针对单一平台反复重写的低效路径。 根据MarkWide Research 发布的跨平台…

作者头像 李华
网站建设 2026/6/22 20:23:47

如何在OSX-KVM中实现GPU直通:3步彻底解决虚拟化性能瓶颈

如何在OSX-KVM中实现GPU直通&#xff1a;3步彻底解决虚拟化性能瓶颈 【免费下载链接】OSX-KVM Run macOS on QEMU/KVM. With OpenCore Monterey Ventura Sonoma support now! Only commercial (paid) support is available now to avoid spammy issues. No Mac system is re…

作者头像 李华