- 博客(102)
- 收藏
- 关注
原创 【Java 开发日记】我们来说一说 JVM 的内存模型
本文系统介绍了JVM内存结构(运行时数据区)的组成及其特性。主要内容包括:程序计数器(线程私有,记录执行位置)、Java虚拟机栈(存储方法调用栈帧)、Java堆(存放对象实例,GC主要区域)、方法区(存储类信息等,JDK8后改为元空间实现)和运行时常量池(存储字面量和符号引用)。此外还介绍了直接内存(NIO使用的堆外内存)。文章对比了各区域的线程共享性、存储内容和可能的内存异常(OOM/SOF),并区分了JVM内存结构与Java内存模型的不同概念。这些知识是理解Java程序运行机制和性能调优的基础。
2025-10-21 15:01:09
1468
69
原创 【Java 开发日记】我们来说一说 Redisson 的原理
前言Redisson 不仅仅是一个 Redis 客户端,它更是一个在 Redis 基础上实现的 Java 驻内存数据网格(In-Memory Data Grid)。它的核心目标是让 Java 开发者能够以最自然的方式使用 Redis,将复杂的 Redis 命令封装成大家熟悉的 Java 接口(如包下的接口)。一、核心设计理念二、核心架构与通信层。
2025-10-20 16:12:21
3552
55
原创 【Java开发日记】请介绍类加载过程,什么是双亲委派模型?
简单来说,类加载过程描述了一个.class文件从磁盘加载到JVM内存,并最终成为一个可用的Class对象的详细步骤。而双亲委派模型则是指导这些类加载器如何协同工作的一套规则,它的核心思想是“自上而下”的检查与“自下而上”的加载,从而保证了Java程序的稳定运行和安全。
2025-10-14 20:51:44
1151
71
原创 【Java 开发日记】我们来说一说什么是 AQS ?
AQS 的核心贡献在于,它提供了一个强大的框架,将复杂的线程排队、阻塞、唤醒等底层操作封装起来,让同步器的开发者只需要关注一个核心问题:如何管理那个state变量。它的优点:极大地降低了构建锁和同步器的复杂度。性能高效:通过自旋、CAS 等无锁编程技术,减少了线程上下文切换的开销。灵活强大:通过两种模式的区分,可以构建出各种复杂的同步工具。如果小假的内容对你有帮助,请评论。创作不易,大家的支持就是我坚持下去的动力!
2025-10-13 20:36:27
13989
73
原创 【Java 开发日记】我们来说一说 Java 自动装箱与拆箱是什么?
要理解“自动”,首先要理解手动的“装箱”和“拆箱”。基本数据类型byteshortintlongfloatdoublecharboolean。它们直接存储“值”,存在于栈内存中,效率高。引用类型:所有Object的子类。它们存储的是对象的“引用”(地址),实际对象存在于堆内存中。在某些场景下(例如使用集合类ArrayListHashMap),我们必须使用引用类型,因为集合只能存储对象。这就产生了在基本类型和其对应的包装类对象之间转换的需求。包装类。
2025-10-12 16:10:53
1607
78
原创 【Java开发日记】线程池执行过程中遇到异常该怎么办?
1、线程池中线程中异常尽量手动捕获2、通过设置的可以对未捕获的异常做保底处理,通过execute提交任务,线程依然会中断,而通过submit提交任务,可以获取线程执行结果,线程异常会在get执行结果时抛出。如果小假的内容对你有帮助,请评论。创作不易,大家的支持就是我坚持下去的动力!
2025-10-09 14:40:10
1615
83
原创 【Java 开发日记】我们来说一说 ThreadLocal 内存泄漏
假设 key 为 25 的并没有进行向前移动,也就是它还在位置 7 ,位置 6 是空的,再插入一个 key 为 25 ,经过 hash 应该在位置 5 ,但是有数据了,那就向下走,到了位置 6 ,诶,竟然是空的,赶紧插进去,这不就又造成了上面说到的问题,同样的一个 key 竟然出现了两次?就是因为这条引用链的存在,就会导致如果 Thread 还在运行,那么 Entry 不会被回收,进而 value 也不会被回收掉,但是 Entry 里面的 key 值已经被回收掉了。
2025-09-29 09:32:40
2478
67
原创 【Java 开发日记】我们来说一说动态代理
首先,动态代理是代理模式的一种实现方式,代理模式除了动态代理还有 静态代理,只不过静态代理能够在编译时期确定类的执行对象,而动态代理只有在运行时才能够确定执行对象是谁。代理可以看作是对最终调用目标的一个封装,能够通过操作代理对象来调用目标类,这样就可以实现调用者和目标对象的解耦合。动态代理的应用场景有很多,最常见的就是AOP 的实现、RPC 远程调用、Java 注解对象获取、日志框架、全局性异常处理、事务处理等。
2025-09-27 14:37:26
2607
78
原创 【Java开发日记】说一说 final、finally、 finalize 有什么区别?
类似的,final字段对性能的影响,大部分情况下,并没有考虑的必要。接下来,我来介绍更多设计考虑和实践细节。final变量产生了某种程度的不可变(immutable)的效果,所以,可以用于保护只读数据,尤其是在并发编程中,因为明确地不能再赋值final变量,有利于减少额外的同步开销,也可以省去一些防御性拷贝的必要。final可以用来修饰类、方法、变量,分别有不同的意义,final修饰的class代表不可以继承扩展,final的变量是不可以修改的,而final的方法也是不可以重写的(override)。
2025-09-22 14:46:24
1484
83
原创 【Java开发日记】我们来说一说 synchronized 和 ReentrantLock 有什么区别?
公平性的选择,其永远是不公平的,这也是主流操作系统线程调度的选择。在Java 5以前,synchronized是仅有的同步手段,在代码中, synchronized可以用来修饰方法,也可以使用在特定的代码块儿上,本质上synchronized方法等同于把方法全部语句用synchronized块包起来。synchronized是Java内建的同步机制,所以也有人称其为Intrinsic Locking,它提供了互斥的语义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能等待或者阻塞在那里。
2025-09-22 14:43:15
2362
66
原创 【Java开发日记】我们来说说当一个线程两次调用 start() 方法会出现什么情况?
等待(WAITING),表示正在等待其他线程采取某些操作。从操作系统的角度,可以简单认为,线程是系统调度的最小单元,一个进程可以包含多个线程,作为任务的真正运作者,有自己的栈(Stack)、寄存器(Register)、本地存储(Thread Local)等,但是会和进程内其他线程共享文件描述符、虚拟地址空间等。尤其是在多核CPU的系统中,线程等待存在一种可能,就是在没有任何线程广播或者发出信号的情况下,线程就被唤醒,如果处理不当就可能出现诡异的并发问题,所以我们在等待条件过程中,建议采用下面模式来书写。
2025-09-18 20:09:23
1410
68
原创 【Java开发日记】我们来说说 Java 是如何实现线程间通信?
正常情况下,每个子线程完成各自的任务就可以结束了。不过有的时候,希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了。下面从几个例子作为切入点来讲解下 Java 里有哪些方法来实现线程间通信。如何让两个线程依次执行?如何让 两个线程按照指定方式有序交叉运行呢?四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的三个运动员各自准备,等到三个人都准备好后,再一起跑。
2025-09-15 14:25:43
2109
12
原创 【Java 开发日记】我们来说一说如何使用 Lambda 表达式实现排序功能
Test// 按 name 倒序// 字母序 T > J/* ---------- 最小 Student 实现 ---------- */在Stream中的操作与直接列表排序类似,可以反转Comparator定义,也可以使用反转。@Test@Test。
2025-09-11 19:47:34
1618
77
原创 【Java开发日记】该如何创建正确的线程池?
虽然在Java语言中创建线程看上去就像创建一个对象一样简单,只需要new Thread()就可以了,但实际上创建线程远不是创建一个对象那么简单。创建对象,仅仅是在JVM的堆里分配一块内存而已;而创建一个线程,却需要调用操作系统内核的API,然后操作系统要为线程分配一系列的资源,这个成本就很高了,所以线程是一个重量级的对象,应该避免频繁创建和销毁。那如何避免呢?应对方案估计你已经知道了,那就是线程池。线程池的需求是如此普遍,所以Java SDK并发包自然也少不了它。
2025-09-08 14:44:50
1623
78
原创 【Java开发日记】我们来说一说 Cglib 与 JDK 动态代理
用起来很简单,其实,这基本上就 AOP 的一个简单实现了,在目标对象的方法执行之前和 执行之后进行了增强。从结果可以看出,代理类会实现我们的接口,并会实现我们接口中的方法。在invoke中可以使用反射去执行原有逻辑,并在方法执行前后加上自己的增强逻辑。JdkDynamicAopProxy是Spring中JDK动态代理的实现,它也实现了InvocationHandler接口。创建自定义的 InvocationHandler,用于对接口提供的方法进行增强。构造函数,将代理的对象传入。创建业务接口 实现类。
2025-09-06 17:15:39
1303
73
原创 【Java 开发日记】我们来说一说解决线程安全的方案
使用线程安全的类,如类;使用锁或加锁排队执行;使用线程本地变量 ThreadLocal 来处理。如果小假的内容对你有帮助,请评论。创作不易,大家的支持就是我坚持下去的动力!
2025-09-02 09:05:37
1342
95
原创 【Java开发日记】我们来讲一讲 Channel 和 FileChannel
NIO 中通过 Channel 封装了对数据源的操作,通过 Channel 可以操作数据源,但是又不必关注数据源的具体物理结构,这个数据源可以是文件,也可以是socket。方法即可从 FileChannel 中获取数据,当然不是直接获取,而是需要先写入到 Buffer 中,所以调用。,该方法返回 int 表示有多少数据读取到了 Buffer 中了,如果返回 -1 表示已经到文件末尾了。方法实现一模一样,先确定该 Channel 是打开的,然后加锁,最后调用 IOUtil 的。
2025-08-25 10:18:43
2561
32
原创 【Java 开发日记】我们来说一说 ConcurrentHashMap 是如何保证线程安全的?
在jdk1.7中是采用Segment + HashEntry + ReentrantLock的方式进行实现的,而1.8中放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现。JDK1.8的实现降低锁的粒度,JDK1.7版本锁的粒度是基于Segment的,包含多个HashEntry,而JDK1.8锁的粒度就是HashEntry(首节点)
2025-08-21 20:45:18
1777
89
原创 【Java开发日记】我们来说一说如何正确的停掉线程?
中断和关闭线程的方式五花八门,看起来很相似,其实里头大有门道。处理不好,可是会导致程序崩溃的。如果小假的内容对你有帮助,请评论。创作不易,大家的支持就是我坚持下去的动力!
2025-08-19 15:24:15
4903
76
原创 【Java开发日记】我们来说说 LockSupport 的 park 和 unpark
LockSupport 和 CAS 是Java并发包中很多并发工具控制机制的基础,它们底层其实都是依赖Unsafe实现。很多锁的类都是基于LockSupport的park和unpark来实现的,所以了解LockSupport类是非常重要的。如果小假的内容对你有帮助,请评论。创作不易,大家的支持就是我坚持下去的动力!
2025-08-18 14:58:18
21222
85
原创 【Java 开发日记】一个不注意就死锁了,该怎么办呢?
当我们在编程世界里遇到问题时,应不局限于当下,可以换个思路,向现实世界要答案,利用现实世界的模型来构思解决方案,这样往往能够让我们的方案更容易理解,也更能够看清楚问题的本质。但是现实世界的模型有些细节往往会被我们忽视。因为在现实世界里,人太智能了,以致有些细节实在是显得太不重要了。在转账的模型中,我们为什么会忽视死锁问题呢?原因主要是在现实世界,我们会交流,并且会很智能地交流。而编程世界里,两个线程是不会智能地交流的。所以在利用现实模型建模的时候,我们还要仔细对比现实世界和编程世界里的各角色之间的差异。
2025-08-11 13:02:28
9553
86
原创 【Java 开发日记】我们来说一说 悲观锁、乐观锁、分布式锁的使用场景和使用技巧
最后来总结一下,如果可以非常熟练的解决这类问题,第一时间肯定想到的是:数据库版本号解决方案或者分布式锁的解决方案;但是如果是一个初学者,一定会第一时间考虑到Java中提供的同步锁或者数据库行锁。如果小假的内容对你有帮助,请评论。创作不易,大家的支持就是我坚持下去的动力!
2025-08-07 15:05:12
3463
131
原创 【Java 开发日记】我们来简单地讲一讲 Git 工作原理
上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。创作不易,大家的支持就是我坚持下去的动力!如果小假的内容对你有帮助,请。
2025-08-05 10:59:19
1788
21
原创 【Java开发日记】我们来说一说如何保证线程安全
同步只是保证共享数据争用时的正确性的手段,如果一个方法本来就不涉及共享数据,那它自然就无需任何同步操作去保证正确性,因此会有一些代码天生就是线程安全的。CAS指令执行时,CAS指令指令时,当且仅当V处的值符合旧预期值A时,处理器用B更新V处的值,否则它就不执行更新,但是无论是否更新了V处的值,都会返回V的旧值,上述的处理过程是一个原子操作。它需要保证对这个对象单独的操作是线程安全的,在调用的时候不需要做额外的保障措施,但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。
2025-08-04 10:50:10
1783
72
原创 【Java开发日记】我们来讲一讲 ConcurrentHashMap
原来segment里面才是真正的hashtable,即每个segment是一个传统意义上的hashtable,如上图,从两者的结构就可以看出区别,这里就是找出需要的entry在table的哪一个位置,之后得到的entry就是这个链的第一个节点,如果e!这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。
2025-07-26 21:30:51
1297
30
原创 【Java开发日记】我们来说说如何使用 Lambda 表达式实现排序功能
return age;@Test// 使用Comparator.comparing的重载方法,传入Comparator.reverseOrder()实现倒序// 验证排序结果在Stream中的操作与直接列表排序类似,可以反转Comparator定义,也可以使用反转。@Test@Test。
2025-07-21 16:15:50
4500
38
原创 【Java开发日记】详细地讲解一下如何保证线程安全性呢?
时分成了三步,第一步是取出当前内存 count 值,这时 count 值时最新的,接下来执行了两步操作,分别是 +1 和重新写回主存。假设有两个线程同时在执行 count++ ,两个内存都执行了第一步,比如当前 count 值为 5 ,它们都读到了,然后两个线程分别执行了 +1 ,并写回主存,这样就丢掉了一次加一的操作。中,var1就是count,而var2第二个值是当前的值,比如想执行的是2+1=3操作,那么第二个参数是2,第三个参数是1。修饰的,代表是java底层的方法,不是通过java实现的。
2025-07-17 15:20:56
1330
25
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅