深入理解多线程编程和 JVM 内存模型
文章目录
- 1. 理解进程和线程的概念
- 进程(Process)
- 线程(Thread)
- 2. 理解竞态条件和死锁
- 竞态条件(Race Condition)
- 死锁(Deadlock)
- 3. JVM 内存模型
- 堆(Heap)
- 栈(Stack)
- 方法区(Method Area)
- 本地方法栈(Native Method Stack)
- PC 寄存器(Program Counter Register)
- 垃圾回收
- 4. 常见的多线程编程模式
- 生产者-消费者模式
- 线程池模式
- 并发集合
- 结论

🎉欢迎来到Java面试技巧专栏~深入理解多线程编程和 JVM 内存模型
- ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹
- ✨博客主页:IT·陈寒的博客
- 🎈该系列文章专栏:Java面试技巧
- 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习
- 🍹文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
- 📜 欢迎大家关注! ❤️
在现代软件开发中,多线程编程已经成为不可或缺的一部分。多线程使得我们可以更好地利用多核处理器,提高应用程序的性能。但多线程编程也伴随着一系列挑战,如竞态条件(race condition)和死锁。本文将探讨多线程编程的基本概念,JVM 内存模型,以及常见的多线程编程模式。
1. 理解进程和线程的概念
进程(Process)
进程是操作系统中的一个独立的执行单元,拥有自己的内存空间、文件描述符、以及系统资源。每个进程都运行在自己的独立地址空间中,互不干扰。进程之间的通信通常需要复杂的机制,如进程间通信(IPC)。
示例代码:
import os# 获取当前进程的 ID
print("当前进程 ID:", os.getpid())# 创建新进程
if os.fork() == 0:print("子进程 ID:", os.getpid())
else:print("父进程 ID:", os.getpid())
线程(Thread)
线程是进程中的执行单元,多个线程可以共享同一个进程的内存和资源。线程之间的通信相对容易,因为它们共享相同的地址空间。但也因为共享,线程之间需要特殊的同步机制来避免竞态条件等问题。
示例代码:
public class MyThread extends Thread {public void run() {System.out.println("线程执行");}public static void main(String[] args) {MyThread thread = new MyThread();thread.start();}
}
2. 理解竞态条件和死锁
竞态条件(Race Condition)
竞态条件指的是多个线程同时访问共享数据时,由于执行顺序不确定而导致的不确定行为。竞态条件可以导致程序出现不一致的结果,因此需要适当的同步机制来避免。
示例代码:
public class RaceConditionExample {private static int sharedCounter = 0;public static void main(String[] args) {Runnable incrementTask = () -> {for (int i = 0; i < 1000; i++) {sharedCounter++;}};Thread thread1 = new Thread(incrementTask);Thread thread2 = new Thread(incrementTask);thread1.start();thread2.start();try {thread1.join();thread2.join();System.out.println("共享计数器的值: " + sharedCounter);} catch (InterruptedException e) {e.printStackTrace();}}
}
死锁(Deadlock)
死锁是指两个或多个线程互相等待对方释放资源而无法继续执行的情况。死锁通常发生在多个线程试图获取多个锁的情况下,如果锁的获取顺序不当,就可能导致死锁。
示例代码:
public class DeadlockExample {private static final Object lock1 = new Object();private static final Object lock2 = new Object();public static void main(String[] args) {Thread thread1 = new Thread(() -> {synchronized (lock1) {System.out.println("Thread 1: 持有锁1...");try { Thread.sleep(100); } catch (InterruptedException e) {}System.out.println("Thread 1: 尝试获取锁2...");synchronized (lock2) {System.out.println("Thread 1: 获取到锁2...");}}});Thread thread2 = new Thread(() -> {synchronized (lock2) {System.out.println("Thread 2: 持有锁2...");try { Thread.sleep(100); } catch (InterruptedException e) {}System.out.println("Thread 2: 尝试获取锁1...");synchronized (lock1) {System.out.println("Thread 2: 获取到锁1...");}}});thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}}
}
3. JVM 内存模型
JVM(Java Virtual Machine)内存模型定义了 Java 程序在内存中的数据存储和访问规则。JVM 内存模型将内存划分为不同的区域,如堆、栈、方法区等。
堆(Heap)
堆是用于存储对象实例的内存区域。所有通过 new
关键字创建的对象都存储在堆中。堆中的对象可以被多个线程共享。
栈(Stack)
栈是用于存储方法调用的内存区域。每个线程都拥有自己的栈,用于存储方法的局部变量和方法调用的信息。栈中的数据只能由所属线程访问。
方法区(Method Area)
方法区用于存储类信息、静态变量、常量池等数据。它也是多线程共享的区域。
本地方法栈(Native Method Stack)
本地方法栈用于执行本地方法,通常由 C 或 C++ 编写。本地方法栈中的数据只能由本地方法访问。
PC 寄存器(Program Counter Register)
PC 寄存器用于存储当前线程执行的字节码指令地址。它是线程私有的。
垃圾回收
JVM 负责自动进行垃圾回收,以释放不再使用的对象占用的内存。垃圾回收算法和策略对程序的性能和内存消耗有重要影响。
4. 常见的多线程编程模式
生产者-消费者模式
生产者-消费者模式是一种经典的多线程编程模式,用于解决生产者和消费者之间的协作问题。生产者线程生产数据并将其放入缓冲区,消费者线程从缓冲区中取出数据并进行处理。
示例代码:
import java.util.LinkedList;public class ProducerConsumerExample {private LinkedList<Integer> buffer = new LinkedList<>();private int capacity = 2;public void produce() throws InterruptedException {int value = 0;while (true) {synchronized (this) {while (buffer.size() == capacity) {wait();}System.out.println("生产者生产: " + value);buffer.add(value++);notify();Thread.sleep(1000);}}}public void consume() throws InterruptedException {while (true) {synchronized (this) {while (buffer.isEmpty()) {wait();}int value = buffer.poll();System.out.println("消费者消费: " + value);notify();Thread.sleep(1000);}}}public static void main(String[] args) {ProducerConsumerExample example = new ProducerConsumerExample();Thread producerThread = new Thread(() -> {try {example.produce();} catch (InterruptedException e) {e.printStackTrace();}});Thread consumerThread = new Thread(() -> {try {example.consume();} catch (InterruptedException e) {e.printStackTrace();}});producerThread.start();consumerThread.start();}
}
线程池模式
线程池模式是为了重用线程,减少线程的创建和销毁开销。线程池可以管理多个线程,并为它们分配任务。
示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);Runnable task1 = () -> {System.out.println("任务1执行");};Runnable task2 = () -> {System.out.println("任务2执行");};executor.submit(task1);executor.submit(task2);executor.shutdown();}
}
并发集合
Java 提供了一些并发集合类,如 ConcurrentHashMap
和 `
ConcurrentLinkedQueue`,用于在多线程环境中安全地操作集合数据。
示例代码:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentMapExample {public static void main(String[] args) {Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();concurrentMap.put("one", 1);concurrentMap.put("two", 2);int value = concurrentMap.get("one");System.out.println("Value: " + value);}
}
结论
多线程编程是现代软件开发的重要组成部分,但也伴随着一系列挑战。程序员需要深入理解多线程的概念、JVM 内存模型,以及常见的多线程编程模式,来编写安全和高效的多线程应用程序。同时,了解垃圾回收、线程池和并发集合等工具和技术也是提高多线程编程能力的关键。
希望本文的内容能帮助读者更好地理解多线程编程,提高在多线程环境下开发应用程序的能力。不同的应用场景和需求可能需要不同的多线程编程模式和技术,因此不断学习和实践是非常重要的。多线程编程是一个复杂而有趣的领域,也是软件开发的重要一部分。
🧸结尾 ❤️ 感谢您的支持和鼓励! 😊🙏
📜您可能感兴趣的内容:
- 【Java面试技巧】Java面试八股文 - 掌握面试必备知识(目录篇)
- 【Java学习路线】2023年完整版Java学习路线图
- 【AIGC人工智能】Chat GPT是什么,初学者怎么使用Chat GPT,需要注意些什么
- 【Java实战项目】SpringBoot+SSM实战:打造高效便捷的企业级Java外卖订购系统
- 【数据结构学习】从零起步:学习数据结构的完整路径
相关文章:

深入理解多线程编程和 JVM 内存模型
文章目录 1. 理解进程和线程的概念进程(Process)线程(Thread) 2. 理解竞态条件和死锁竞态条件(Race Condition)死锁(Deadlock) 3. JVM 内存模型堆(Heap)栈&am…...

QML(25)——文本输入框组件的区别(TextField TextInput TextArea TextEdit)
目录 效果展示适用场景文本组件TextLabelText和Label的区别 单行文本输入框TextFieldTextInputTextField 和 TextInput的区别 多行文本输入框TextAreaTextArea 和 TextEdit 的区别 效果展示 适用场景 场景组件属性短文本Text长文本 末尾省略Textelide: Text.ElideRight文本设置…...

SpringBoot连接MySQL密码错误,报错:Access denied for user
记:一次连接MySQL报密码错误,Access denied for user 检查步骤: 核对用户和密码是否正确,用工具登陆试下。如果配置文件是yml格式,配置密码是123456这种纯数字,记得加上单/双引号。检查云上数据库配置&am…...

如何使用visual studio 2010构建SQLite3.lib文件
sqlite3官网只提供了dll,并没有lib文件。需要自己生成sqlite3.lib。因项目升级到x64,以前并没有生成64位的链接库,需要自己创建。本人电脑操作系统windows 10, 开发环境为visual studio 2010。下面是详细生成过程。 1. 从源下载源(…...

反转链表review
反转链表 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; }* }*/ class …...

UG\NX二次开发 获取用户默认设置中的绘图信息 UF_PLOT_ask_session_job_options
文章作者:里海 来源网站:《里海NX二次开发3000例专栏》 感谢粉丝订阅 感谢 m0_58724732 订阅本专栏,非常感谢。 简介 UG\NX二次开发 获取用户默认设置中的绘图信息 UF_PLOT_ask_session_job_options 效果 代码 #include "me.hp...

数字图像处理实验记录五(图像的空间域增强-锐化处理)
前言: 文章目录 一、基础知识1,什么是锐化?2,为什么要锐化?3,怎么进行锐化? 二、实验要求任务1:任务2:任务3: 三、实验记录:任务1:任…...

基于水基湍流优化的BP神经网络(分类应用) - 附代码
基于水基湍流优化的BP神经网络(分类应用) - 附代码 文章目录 基于水基湍流优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.水基湍流优化BP神经网络3.1 BP神经网络参数设置3.2 水基湍流算法应用 4.测试结果…...
0010【Edabit ★☆☆☆☆☆】Maximum Edge of a Triangle
【Edabit 算法 ★☆☆☆☆☆】Maximum Edge of a Triangle algorithms math numbers Instructions Create a function that finds the maximum range of a triangle’s third edge, where the side lengths are all integers. Examples nextEdge(8, 10) // 17 nextEdge(5, 7…...

Godot 官方2D C#重构(3):TileMap使用
文章目录 前言Godot Tilemap使用Tilemap使用TileSet和TilemapTilemap 图片资源添加TileSet,开始切图导入图片切图 简单添加TileMap如何使用 Auto Tilemap使用Auto Tilemap 前言 Godot 官方 教程 Godot 2d 官方案例C#重构 专栏 Godot 2d 重构 github地址 Godot Tilem…...

6.DApp-用Web3实现前端与智能合约的交互
题记 用Web3实现前端与智能合约的交互,以下是操作流程和代码。 准备ganache环境 文章地址:4.DApp-MetaMask怎么连接本地Ganache-CSDN博客 准备智能合约 文章地址: 2.DApp-编写和运行solidity智能合约-CSDN博客 编写index.html文件 <!…...
数据异常值检测
数据异常值检测 参考: 数据异常值的检测方法-基于Python 独家 | 每个数据科学家应该知道的五种检测异常值的方法(附Python代码) 异常检测主要方法总结 14种数据异常值检验的方法! 14种数据异常值检验的方法 浅谈数据挖掘中的…...
监听redis键失效事件实现延迟功能
用Redis实现延迟队列,我研究了两种方案,发现并不简单 SpringBoot实现Redis失效监听事件—KeyExpirationEventMessageListener Redis 监听过期的key(KeyExpirationEventMessageListener) 项目背景 需求上说,需要延迟…...

使用UniApp实现视频数组自动下载与播放功能:一步步指导
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...

C语言笔试面试必刷题
🎊【面经】专题正在持续更新中,内含C语言,数据结构,Linux,网络编程等✨,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 - …...

window11安装Python环境
python环境安装 访问Python官网:https://www.python.org/ 点击downloads按钮,在下拉框中选择系统类型(windows/Mac OS/Linux等) 选择下载最新版本的Python cmd命令如果出现版本号以及>>>则表示安装成功 如果出现命令行中输入python出现如下错误 可能…...

SpringBoot中的日志使用
SpringBoot的默认使用 观察SpringBoot的Maven依赖图 可以看出来,SpringBoot默认使用的日志系统是使用Slf4j作为门户,logback作为日志实现 编写一个测试代码看是否是这样 SpringBootTest class SpringbootLogDemoApplicationTests {//使用Slf4j来创建LOG…...
微信小程序中监听横屏竖屏
直接上代码 第一步:在你想要监听页面的json文件中添加此节点 "pageOrientation": "auto" 第二步:wx.onWindowResize() page({ onLoad() {this.kstd()},kstd(){ // 监听屏幕旋转事件 wx.onWindowResize((res)>{// …...

云原生概述
1. 何谓云原生 云原生是一种构建和运行应用程序的方法,是一套技术体系和方法论。云原生(CloudNative)是一个组合词,CloudNative。Cloud表示应用程序位于云中,而不是传统的数据中心;Native表示应用程序从设…...

消失的它:网络层分片包中的第一个分片包去哪了?
在网络层IP包分片的过程中,遇到了大麻烦! 主机A: IP地址:192.168.0.10/24 MAC地址:02:00:00:00:00:10 主机B: IP地址:192.168.0.20/24 MAC地址:02:00:00:00:00:20 MTU:1…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...