- 博客(36)
- 收藏
- 关注
原创 Redis和MySQL双写一致性问题
写操作首先只写入 Redis,不立即写入 MySQL,而是异步地将数据写入 MySQL。这种模式的好处是性能高,但它在一致性上存在风险:如果 Redis 崩溃或网络断开,可能导致 MySQL 中的数据无法更新。共享锁(读锁readLock):一旦加上这个锁,其他线程就可以共享读操作,不会互相干扰,真是好帮手!排他锁(独占锁writeLock):这个锁更霸道,一旦加上,其他线程就别想读写操作了,得乖乖等着。(一般情况下数据库是主从模式,读写分离,使用演示操作,等主节点同步到从节点。这是最常见的策略,也称为。
2024-09-22 09:42:22
418
原创 JVM分代模型:年轻代、老年代、永久代
接着Eden区就会被清空,然后再次分配新对象到Eden区里,然后就会如上图所示,Eden区和一块Survivor区里是有对象的,其中Survivor区里放的是上一次Minor GC后存活的对象。这时,发现他是不能被回收的,因为他被人引用了,而且是被局部变量“replicaManager”引用的。这个就是最普通的代码,一个变量引用一个对象,只要是强引用的类型,那么垃圾回收的时候绝对不会去回收这个对象的。,强引用就是代表绝对不能回收的对象,软引用就是说有的对象可有可无,如果内存实在不够了,可以回收他。
2024-08-02 17:56:36
1531
原创 JVM面试题:年轻代与老年代
大约有三种情况,第一次是 Young GC 发生之前,如果老年代的可用内存小于以往 Young GC 后升入老年代的对象的平均大小,此时就带先触发一次 Old GC(或Major GC),腾出更多空间;第三次是如果老年代的内存使用率超过了 92%,也会直接触发 Old GC。一般有两种情况,第一种是先创建的对象太大了(创建时如果大小超过了新生代Eden区的一定阈值),就会直接进入老年代,另一种是对象的年龄太老了,每发生一次 Minor GC,存活的年龄就 +1,达到默认值 15 就会自动晋升成老年代。
2024-08-02 17:39:15
180
原创 JVM面试题:垃圾回收
比方说 JVM 内存结构中的虚拟机栈,虚拟机栈中有栈帧,栈帧里面存储着有指向堆的对象引用,那么位于虚拟机栈顶的栈帧就可以称作是 “活跃” 的栈帧,因为此刻它正在被线程调用。这个过程简单粗暴,但也存在内存碎片问题,导致可能我有 10M 的内存,但程序申请 9M 的空间却会失败,也就是说整个内存空间的 10M 是不连续的。这个过程叫做 “标记复制算法”。那就不如折中一下,可以在标记之后,把存活的对象移到当前空间的一边,把垃圾移到另一边,然后再清除,就没有内存碎片的问题,同时内存利用率也不会降低。
2024-08-02 17:35:04
333
原创 JVM面试题:类加载
还有比如 JDBC 也算是破坏了双亲委派模型,当我们使用 JDBC 时,是用 DriverManager.getConnection( ) 来获取连接的,但由于 DriverManager 本身是属于 Java 包下的,是由 BootStrapClassLoader 加载的,而通过 getConnection 得到的是其它厂商的实现类,显然是不能由 BootStrapClassLoader 加载。如果父加载器可以找到并加载这个类,那么这个类加载的请求就结束了,否则,子加载器才会尝试加载该类,以此类推。
2024-07-25 17:19:38
561
原创 JVM面试题:内存模型
排查时可以通过性能检测工具如 jconsole,获取堆内存快照,然后观察溢出的对象是否是必要的,是的话就需要检查代码中对象的生命周期是否过长,或者优化算法,实在不行可以调整 JVM 的堆参数设置 -Xmx 和 -Xms,增加 JVM 最大内存和启动初始内存;如果溢出的对象不是必要的,就表明发生了内存泄漏,这时可以查看泄漏对象的 GC Roots 引用链,找到具体泄漏的位置。对于符号引用,其中包括类的全限定名,方法名等等,主要用在类加载,动态绑定等阶段,来定位具体的类,方法等等。同时堆中分配的内存由。
2024-07-25 17:14:08
779
原创 JVM:内存区域划分
栈绝对算的上是 JVM 运行时数据区域的一个核心,除了一些 Native 方法调用是通过本地方法栈实现的(后面会提到),其他所有的 Java 方法调用都是通过栈来实现的(也需要和其他运行时数据区域比如程序计数器配合)。和数据结构上的栈类似,两者都是先进后出的数据结构,只支持出栈和入栈两种操作。方法调用的数据需要通过栈进行传递,每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。的,它的生命周期和线程相同,随着线程的创建而创建,随着线程的死亡而死亡。
2024-07-25 16:30:36
321
原创 JVM:类加载机制
在加载一个类之前,类加载器会先委派给它的父加载器去尝试加载这个类。这个过程会一直向上递归,从而首先使得启动类加载器有机会去加载这个类。:当所有的父加载器都无法加载该类时,最初收到加载请求的类加载器(如应用程序类加载器)会尝试自己加载这个类。:当应用需要加载一个类时,它会把这个请求传递给加载它的类加载器。这样的话,可以避免多层级的加载器结构重复加载某些类。
2024-07-25 15:40:53
181
原创 Java集合:List和Set
其中 List 接口会维护元素的插入顺序,并且允许根据索引进行数据查询和操作。而 Set 接口只强调元素的不可重复性,不保证元素的特定顺序,也不支持索引查询。Set 接口常见的实现类有 HashSet,TreeSet 等,前者底层为哈希表,提供快速的插入,删除和查找性能,但不保证元素的顺序。后者底层为红黑树,元素间可以使用自定义比较器进行排序。List 接口常见的实现类有 ArrayList,LinkedList 等,前者底层为数组,适合随机访问多的场景。后者底层为双向链表,适合插入删除操作多的场景。
2024-07-24 14:49:36
146
原创 Java集合:ConcurrentHashMap
JDK 1.8 为了摆脱哈希表中 Segment 个数对并发度的限制,底层采用和 HashMap 类似的实现:数组 + 链表 + 红黑树,加锁用 CAS 和 synchronized 实现。如果槽位不为空,则需要进一步判断其它线程是否在对其扩容,是则协助扩容,不是则使用 synchronized 锁住当前槽位,再进行插入节点操作。任务为 Key,任务的执行状态为 Value,多个线程可以同时查找和更新任务的状态,实现对多任务的控制。
2024-07-23 18:55:55
250
原创 Java基础:ArrayList和LinkedList
ArrayList 的默认容量为 10,当需要扩容时,会先申请一个容量为旧容量 1.5 倍的新数组,然后把旧数组复制到新数组中。LinkedList 底层使用双向链表实现的,由于每个节点都含有前驱和后继节点的引用,所以它插入删除时只需修改这些引用,效率要比 ArrayList 高。ArrayList 首先会以 O(1) 时间定位到第 k 个元素,然后将被这个元素分割的两部分复制拼接到一个新数组上,总体为 O。) 时间定位到第 k 个元素,然后 O(1) 时间处理这个元素前后节点的引用,总体也为 O。
2024-07-23 18:49:38
866
原创 Java集合: HashMap
这个在源码的注释中有解释,大致意思为:如果元素的哈希值足够随机,理想情况下链表的长度对应的概率符合泊松分布,达到 8 的概率小于千万分之一。JDK 1.7 的 HashMap 底层为数组 + 链表,扩容的 transfer( ) 会遍历原链表中的每个节点,采用头插法将其转移到新哈希表槽位的链表中,这个过程在多线程下会导致新链表中出现环路,并造成某些元素丢失。采用头插法的话,最新插入的数据就会在链表的最前边,根据程序的局部性原理,最近被访问的数据很可能不久之后会再次访问,那么此时可以在 O(1) 时间返回。
2024-07-23 15:43:39
923
原创 Java高频面试题:Java基础
4. 讲一下equals()与hashcode(),什么时候重写,为什么重写,怎么重写?11. String、StringBuilder、StringBuffer有什么区别?12. 什么是序列化?什么情况下需要序列化?序列化在Java中是怎么实现的?7. 谈一谈你对 final 关键字的理解?什么需要用这个关键字来定义呢?13. Java 中的反射是什么意思?14. 什么是动态代理?3. = =和equals有什么区别?5. 讲一下重载和重写的区别?10. 聊一聊你对多态的理解?6. 抽象和接口的区别?
2024-07-22 16:26:34
693
原创 Java基础:反射
反射就是在 Java 程序运行的过程中,动态获得某个类的方法变量,并调用的技术。反射的缺点主要有两个。如图是类的正常加载过程:反射的原理在于class对象。cr.
2024-07-22 16:12:13
1110
原创 Java基础:序列化与反序列化
1:序列化就是指将 Java 对象转换成二进制字节流的过程。当我们需要对某些对象进行时,需要先对它们序列化成二进制字节序列,然后存到数据库或者内存中。或者两个 Java 进程远程通信时,也需要将 Java 对象转换为字节序列才能在网络中传送。首先被序列化的对象一定需要实现 Serializable 或 Externalizable 接口。
2024-07-20 13:29:31
666
原创 Java基础:String、StringBuilder、StringBuffer有什么区别?
类还提供了很多修改字符串的方法比如。StringBufferl类(继承自。
2024-07-20 13:10:20
478
原创 Java基础:多态
那么在之后的支付代码中,无论用户选择的哪种支付方式,都可以统一用 Payment 来进行具体的 pay 操作。另外,在修改具体的支付逻辑时,也只需单独去微信或者支付宝的类里面去修改,而不用动主逻辑里面的代码,体现出多态的灵活和可扩展性。除了以上说的运行时多态,我还听说过一个有争议的编译时多态,它具体指 Java 中的方法重载,在编译期就根据已知的参数列表,决定了需要调用的方法。拿继承来说,子类必须重写父类的方法,通过向上转型,使用父类类型来调用子类对象的方法,结果是在运行时执行子类中重写的方法。
2024-07-20 10:41:16
338
原创 Java基础:String类
String 在源码中使用 char[] 来维护字符序列的,而 char[] 的长度是 int 类型,所以理论上 String 的长度最大为 2^31−1 ,占用空间大约为 4 GB,不过根据实际 JVM 的堆内存限制,编译时,String长度最多可以是2的16次方减2,运行时长度最多可以是2的31次方减1,意思是可以在编译时定义一些短的字符串,运行时可以进行拼接,长一点也可以。除此之外,基于 String 的不可变,Java 使用常量池来尽可能的共享相同的字符串,来节约 String 的存储空间。
2024-07-20 01:09:49
441
原创 Java基础:异常
如果有异常,才会去查异常表,再跳转到对应的 catch 块位置去执行,这个过程可能会影响性能。其次,有时多个方法可能会抛出相同类型的异常,如果每个方法都用 try catch 会非常冗余,这时可以在这些方法中只 throw,在调用这些方法的地方整体 try catch,统一进行处理。但是需要考虑一种特殊情况,就是如果 try 块中抛出了异常但没有被 catch 捕获,且此时 finally 中也抛出了异常,那么 finally 中的异常会覆盖掉 try 中的异常,成为这个方法最终抛出的异常。
2024-07-19 21:45:38
403
原创 Java基础:final关键字
如果是引用类型,引用指向的地址值不变,但地址的内容可能会变。比如Java的一些核心类库的类的API接口不想被纂改就使用final修饰方法。Java希望String类是不可变的,就使用final修饰String类并且修饰成员变量char[]数组,并且没有提供setter方法,这样就可以确保String类是不可变的。另外,如果有多个线程操作同一个变量,并且这个变量的值不会变化,可以考虑使用final修饰解决线程安全问题。final是Java中的一个关键字,可以用来修饰类、方法、变量。
2024-07-19 21:35:44
236
原创 Java基础:抽象和接口的区别?
代码复用和设计规范:抽象类提供了一种机制,允许定义一些基础功能的实现,同时留出抽象方法由子类具体实现。这不仅可以实现代码复用,还能规范子类的行为。例如,定义一个Animal抽象类,其中可以实现一些通用方法如eat和sleep,并留出抽象方法如makeSound供不同的动物类具体实现。限制和规范:抽象类可以定义构造函数,通过构造函数可以完成一些初始化操作,同时可以设定一些类内部的逻辑或状态初始化,这是接口做不到的。单继承的限制:由于Java不支持多重继承,抽象类的使用受到了限制。
2024-07-19 18:20:47
302
原创 Java基础:讲一下equals()与hashcode(),什么时候重写,为什么重写,怎么重写?
原因在于添加第二个 Person 时,先比较的是两个 Person 的 hashCode( ),注意此时我们没有重写 hashCode( ) ,那么分别 new 出来的 Person 的哈希值肯定是不同的,到这里 HashMap 就会将两个 Person 认定为不同的元素添加进去。首先 equals( ) 是 Object 中的方法,默认是用 = = 来比较的。hashCode( ) 也是 Object 类的方法,根据一定的规则将与对象相关的信息,比如对象的内存地址,映射成一个数值,这个数值称作为哈希值。
2024-07-19 17:33:15
427
原创 Java基础:介绍一下Object常见方法
Object 类常见的方法有 toString( ),equals( ) 和 hashCode( ),wait( ) 和 notify( ) 等等。
2024-07-19 17:28:26
398
原创 Java基础:= =和equals有什么区别?
equals 是超类 Object 中的方法,默认是用 = = 来比较的。也就是说,对于没有重写 equals 方法的子类,equals 和 = = 是一样的。对于重写的 equals 方法,比的内容取决于这个方法的实现。“==”是操作符,在比较时,根据所比较的类的类型不同,功能也有所不同:对于基础数据类型,如 int 类型等,比较的是具体的值;而对于引用数据类型,比较的是引用的地址是否相同。
2024-07-19 17:27:07
342
原创 Redis面试题:什么是Redis
Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Hash(哈希)、 List (列表)、Set(集合)、Zset(有序集合)、Bitmaps(位图)、HyperLogLog(基数统计)、GEO(地理信息)、Stream(流),并且对数据类型的操作都是。Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此。负责的,不存在并发竞争的问题。除此之外,Redis 还支持。
2024-07-19 16:58:03
120
原创 Spring面试题:Bean的生命周期(小米三面)
什么是JavaBean?(最简单易懂的定义,内附例子)_java bean到底是啥-优快云博客public 修饰的类 ,public 无参构造所有属性(如果有) 都是private,并且提供set/get (如果boolean 则get 可以替换成is)在 Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。bean是对象,一个或者多个不限定bean由Spring中一个叫IoC的东西管理。
2024-07-02 07:48:20
1640
原创 Spring面试题:Spring IoC原理(tplink一面)
一篇文章讲透spring ioc (概念、原理、实例、应用场景、面试题)_谈谈springioc的理解,原理与实现-优快云博客IoC翻译成中文为控制反转。意思可以理解为类与类之间的依赖通过容器来控制、配置实现原来类与类之间在编译时即产生了依赖,即new对象时,已建立好两者之间的依赖关系IoC机制将两者之间的依赖关系通过容器进行控制,通过注解的方式,在运行时阶段,动态的将某种依赖注入到类当中。IoC主要通过反射原理实现IoC。
2024-06-29 08:59:22
760
原创 设计模式(4)建造者模式
在这模式中,客户不需要知道复杂对象的内部组成和装配方式,只需要知道建造者的类型即可,同时,复杂对象的构建和组装会分隔开来,建造者可以定义不同的创建类型。建造者模式(Builder Pattern)是一种创建型设计模式,也叫生成器模式。它用于构造一个复杂的对象,同时允许。如果产品内部发生变化 , 建造者也要相应修改。建造类之间相互独立 , 在一定程度上解耦。对象的组成部分必须按照某种顺序构建。产生多余的 Builder 对象。3. 建造者模式和工厂模式。2. 建造者模式优缺点。1. 建造者模式简介。
2024-06-29 08:18:02
348
原创 设计模式(0)SOLID原则
Liskov Substitution Principle: 里氏替换原则。Single Responsibility Principle: 单一职责原则。Interface Segregation Principle: 接口隔离原则。Dependence Inversion Principle: 依赖倒置原则。
2024-06-28 16:25:02
286
原创 设计模式(3)观察者模式——简介和SpringBoot应用
观察者模式(Observer Pattern)是一种行为设计模式,又称为发布/订阅(Publish/Subscribe)模式,它定义了对象间的一种一对多的依赖关系,使得当一个对象状态改变时,它的所有依赖对象都会被自动通知并且更新。短信Service实现ApplicationListener接口。举例:用户注册之后发送短信通知、积分还有优惠券。2. SpringBoot观察者模式。优惠券Service直接在。1. 观察者模式简介。观察者模式的使用场景。
2024-06-28 16:07:08
503
原创 设计模式(2)工厂模式——简单工厂/工厂方法/抽象工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,但将对象的实例化逻辑从客户代码中解耦出来。工厂模式通常通过定义一个专门的工厂类来实现,该类对外暴露一个创建对象的接口,而不需要客户代码指定具体类。简单工厂模式不是一个标准的设计模式,更多的是一种编程习惯。它有一个中心化的工厂类,决定哪一个产品类应该被实例化。工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。抽象工厂模式是工厂方法模式的升级版,后者面向单个产品,而前者面向的的是一个产品族。
2024-06-28 15:02:32
214
原创 设计模式(1)单例模式——创建、破坏和防御
时,都会进行线程同步,这可能会引起重大的性能问题),所以不推荐使用。但是这两种修改方法会使代码的效率变的很低(每次调用。
2024-06-28 10:59:39
536
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人