- 博客(18)
- 收藏
- 关注
原创 Zookeeper 是什么?
线程将当前 zxid 最大的 Server 设置为当前 Server 要推荐的 Leader,如果此时获胜的 Server 获得 n/2+1 的 Server 票数,设置当前推荐的Leader 为获胜的 Server ,将根据获胜的 Server相关信息设置自己的状态,否则,继续这个过程,直到 Leader被选举出来。这样的设计有效的减轻了服务端的压力,不然对于更新非常频繁的节点,服务端会不断的向客户端发送事件通知,无论对于网络还是服务端的压力都非常大。但是听朋友说,实际场景下,貌似发生过脑裂问题。
2023-08-28 17:37:35 777 1
原创 RPC项目
客户端的的启动类为TcpClient,通过该类的静态方法实现netty客户端的初始化,同时客户端会向zookeeper获取服务器列表与服务器相连,在启动过程中,会对指定的方法完成动态代理,因为rpc的本质就是向调用本地方法一样进行网络通信,所以动态代理的目的就是完成通信过程中的配置,比如将调用方法和要传递的参数封装成一个request发送给服务器,从而实现对调用者隐藏通信细节的目的。最后基于Zookeeper的watcher机制完成了客户端对服务器节点的监视功能。
2023-08-03 17:04:29 148
原创 Java底层原理——HashTable 和 ConcurrentHashMap详解
减小请求同一个锁的频率减少持有锁的时间ConcurrentHashMap的高并发行主要来自于三个方面用分离锁实现多个线程间的更深层次的共享访问用HashEntry对象的不变性来降低执行读操作的线程在遍历链表期间对加锁的需求通过对同一个volatile变量的写/读访问,协调不同线程间读/写的内存可见性。
2023-03-16 10:39:58 749
原创 Java底层原理——HashMap面试问题
如果超过了负载因子,则会resize一个长度两倍的HashMap,并且在Java7中进行链表元素迁移的时候会进行rehash。而在java8中进行了一些优化,不需要进行rehash,什么优化呢?由于HashMap的长度为2的次幂所以扩容的时候需要迁移的链表元素有两种情况,要么桶下标不变,要么变为桶下标大小加上原来的HashMap的长度大小,决定一个链表元素是那种情况只在于新加入的1bit是0还是1。
2023-03-16 10:35:13 234
原创 Java底层原理——HashMap底层原理(JDK1.8)
从1.7中可知HashMap是数组+链表的结构,HashMap在JDK1.8中加入了的实现,当链表长度大于8时,转换为红黑树的结构。java8中没有indexFor函数,而是直接使用table[index=(n-1)&hash]在JDK1.8中也使用了取代Entry的Node来实现Map.Entry接口Node是一个内部类,实现了Map.Entry接口,本质就是一个键值对。HashMap类中有一个非常重要的字段,就是Node[] table,即哈希桶数组,很明显它是一个Node的数组。
2023-03-16 10:31:51 553
原创 Java底层原理——为什么重写equals方法需同时重写hashCode方法
由于hashcode1不等于hashcode2,导致没有定位到同一个数组位置而返回逻辑上错误的值null(也有可能碰巧定位到同一个数组位置,但是也会判断其entry的hash值是否相等)尽管我们再进行get和put操作的时候,使用的key从逻辑上讲是等值的(通过equals比较是相等的),但由于没有重写hashCode方法,所以put操作时,举一个重写了equals而不重写hashCode会发生什么样的问题。所以再重写equals的方法的时候,必须重写hashCode方法。
2023-03-16 10:29:08 75
原创 Java底层原理——深入理解HashMap(JDK1.7)
数据结构的物理存储结构只有两种:顺序存储结构和链式存储结构,在数组中根据下表查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干是数组。比如我们要新增和查找某个元素,我们通过把当前元素的关键字通过某个函数映射到某个位置上,通过数组下标一次定位就可以完成操作。存储位置= f(关键字)其中这个函数f一般称为哈希函数,这个函数的好坏会直接影响到哈希表的优劣。比如我们要在哈希表中执行插入操作查找操作同理,先通过哈希函数计算出实际存储地址,然后从数组中对应地址取出即可。
2023-03-16 10:26:03 516
原创 JVM——Java应用问题总结
表现为us、sy的值过高Linux在操作文件时,会将数据放进文件缓冲区,因此查看Linux内存状况时经常发现物理内存用的不多,cached用了很多,这是Linux提升文件IO的一种做法。在Linux中,要跟踪线程的文件IO的消耗,主要方法是通过pidstat来查找,输入如pidstat -d -t -p [oud] 1 100(其中-d 、-t、-p为pidstat的参数) ,即可查看线程IO消耗状况,其中KB_rd/s表示每秒读取的KB数,KB_ wr/s表示每秒写入的KB数。
2023-03-16 10:15:02 144
原创 JVM——深入理解类执行机制
在把class文件加载到JVM中且产生了Class对象后,就可以执行Class对象的静态方法和实例化调用了,源码编译阶段源码被编译成JVM字节码,JVM字节码是作为一种中间码的方式,在运行期需要对它进行解释并执行,这种方式称作字节码解释执行方式。
2023-03-15 16:02:49 87
原创 JVM——深入理解线程安全与锁优化
有一个比较恰当的线程安全的定义:当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对 象的行为都可以获得正确的结果,那就称这个对象是线程安全的。
2023-03-15 15:56:32 173
原创 JVM——深入理解JMM(Java内存模型)与线程
让计算机并发执行若干个运算任务,其中一个比较重要的复杂性就在于,许多运算不是只依靠处理器就能实现的,另外还有如读取运算数据、存储运算结果,这种IO操作也都是运算的重要步骤。但是,由于处理器的运算速度和存储设备的IO速度有几个数量级的差距,所以现代计算机不得不在其之间加入一层或多层读写速度尽量接近处理器运算速度的高速缓存。将运算需要用到的数据和运算产生的结果同步到缓存中,这样处理器就无需等待缓慢的内存读写了。
2023-03-15 15:51:59 296
原创 JVM——深入理解虚拟机类加载机制
一个类从进入虚拟机到卸载主要分为加载、验证、准备、解析、初始化、使用、卸载几个阶段,其中验证、准备、解析统称为连接。
2023-03-15 15:47:35 82
原创 JVM——深入理解类加载器
类加载器虽然只应用于类的加载阶段,但它起到的作用远超于此,类加载器可以帮助类确定类的唯一性,相同的两个类(这里指两个类的equals等方法相同)被同一个虚拟机加载,只要他们的类加载器不同即使用的是同一个字节码文件,都会被虚拟机视为不同的两个类。
2023-03-15 15:47:01 99
原创 JVM——深入理解类文件结构
class文件的前4个字节(class文件的显示一般是用的十六进制,一个十六进制数表示半个字节)被称为魔数,它唯一的作用是确定这个文件是不是被java虚拟机可以接受的class文件,其中第5、6个字节标明了次版本号,7、8个字节标明了主版本号。紧接着的两个字节便是标明了常量池中常量的数量这个计数是从1开始的,例如这个002f(47)就是常量池的数量,正确的常量数为47-1也就是46个(通过javap -v *.class访问class的可读性文件 )字面量主要包含一些文本信息和被final修饰的常量等,
2023-03-15 15:39:51 58
原创 JVM——虚拟机性能监控、故障处理工具
jstat [ option vmid [ interval[s|ms] [count] ] ],其中interval和count分别代表查询间隔和次数,如果省略这两个参数说明只查询一次。option表示用户想要查询的虚拟机信息,主要分为三类:类加载、垃圾收集、运行期编译状况。可以列出正在运行的虚拟机进程,并显示虚拟机在执行主类(main() 函数所在的类)命令格式 jstack [ option ] vmid。jstat是用来监视虚拟机各种运行状态信息的工具,jstat的命令格式。
2023-03-15 15:34:28 68
原创 JVM——深入理解垃圾收集器与内存分配
顾名思义标记清除算法分为两个阶段,标记和清除,首先标记出所有需要收集的对象,接着在垃圾收集阶段统一进行回收,这个算法的缺点是体现在”大部分对象都是朝生夕死的“这句话中,大部分对象,其实在标记后都是要回收的,导致该算法的效率其实并不高,并且在清除时会产生空间碎片,如果没有大对象分配空间的话还可以接受,但是如果需要给大对象分配空间,很难找到连续的大空间,必须在存放对象之前进行一次垃圾收集。CMS收集器是一种关注低延迟的垃圾收集器,因此在B/S之类需要和用户交互,需要低延迟的应用中使用。
2023-03-15 15:29:01 84
原创 JVM——深入理解对象的创建、内存分配以及访问定位
类加载检查后就要位新生对象分配内存,对象所需要的内存空间在类加载完成后就可以确定,在Java堆为对象分配空间,其实就是把一个确定大小的内存划分出来存放对象,如果java堆中的内存是非常规整的,所有使用过的内存放在一边,空闲的内存放在另一边,中间放这一个指针作为空间分界点的指示器,那么在给新生对象分配空间时,只需要指针向空闲内存移动一个对象大小的区域即可,而Java堆需要维护一个记录可用和已经使用的内存区域,并在分配对象空间时更新列表,这种方法就叫做指针碰撞。对象的访问定位的实现主流的有两种方式,一种是。
2023-03-15 15:19:00 136
原创 JVM——深入理解Java内存区域
方法区和java堆一样是线程共享的区域,主要存放虚拟器加载的类型信息,常量、静态变量等数据,例如类的版本号、字段、方法的描述信息,java8以前,对方法区的设计是与java堆类似的,并且也打算把收集器的分代设计应用在方法区,所以也一直把方法区叫做永久代,不过经过实践发现,这样的设计更容易导致java应用的内存溢出的问题,于是在java9以后选择了完全放弃永久代,转而用本机内存实现的元空间代替。运行时常量池是方法区的一部分,Class文件中存放编译器生成的各种字面量和符号引用的内容就存放在常量池表中,
2023-03-15 15:18:12 90 1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人