当前位置: 首页>后端>正文

Java系列

【锁机制及原理】

? ? # synchronized

? ? ? ? 只支持非公平锁;

? ? ? ? 不可响应中断;

? ? ? ? 不支持超时获取设置,获取不到时一直等待;

? ? ? ? 锁升级:偏向锁->自旋锁->重量级锁

? ? ? ? ? ? 偏向锁:只有一个线程去竞争,直接获取锁,锁对象里记录该线程id

? ? ? ? ? ? 自旋锁(轻量级锁):另一个线程去竞争已经被占用的锁,偏向锁撤销,俩线程通过自旋+CAS抢占锁,自旋到一定次数升级重量级锁。

? ? ? ? ? ? 重量级锁:锁对象markword里存放的不再是锁记录,还是监视器对象,监视器里包含了等待队列、阻塞队列、当前持有锁线程等;

? ? # reentrantLock

? ? ? ? reentrantLock同时支持公平锁和非公平锁;(在获取锁时实现不同逻辑,1、公平排队 2、和被唤醒的头节点同时竞争(非公平))

? ? ? ? tryLock原理:只尝试获取一次锁,不会加入阻塞队列,通过非公平锁实现方式;

? ? ? ? 可响应中断,长时间获取不到锁,主动中断,避免长时间获取不到,产生死锁;

? ? ? ? 可超时获取锁,设置尝试获取锁时间,超时阻塞;

? ? ? ? Condition:基于AQS实现;wait进入条件队列,被阻塞,唤醒后,会放入AQS同步队列参与争抢锁资源。

? ? # AQS实现原理

? ? 通过state标志获取锁状态(1成功获取同步状态),并记录当前持有锁线程,重复获取锁则state+1,释放锁state-1,

? ? 当state为0时,释放锁,并唤醒阻塞队列中的head节点线程;基于CAS修改状态;

? ? 未获取锁的线程进入阻塞队列(先进先出),进入自旋状态获取锁;

? ? # volitile:

? ? 可见性:共享变量被更改时,cpu发送信号指令将其他工作内存中的有效性置为无效,则其他线程使用该变量时重新去主存获取;

? ? 从内存模型上保证共享安全;共享变量可见性、有序性;但不具备原子性;

? ? synchronized:通过阻塞保障安全;原子性,可见性;但不具备编译指令有序性;

【多线程与高并发】

? ? # 高并发/秒杀抢购场景

? ? 悲观锁:易导致大量线程等待,导致响应时间加大,连接池消耗殆尽,系统陷入异常;

? ? 队列:请求先进入FIFO队列,再处理。导致瞬间占用过多内存,系统异常;处理速度赶不上涌入速度,平均响应时间依旧大;

? ? 乐观锁思想:宽松加锁,基于版本号更新;都有资格更新,版本号符合则成功;缺点:增加cpu计算消耗

? ? 如:redis watch乐观锁,基于版本号比较,实现高并发场景下多次请求的线程安全

? ? # 提高系统并发处理能力:

? ? 1、提高单机硬件和架构性能;

? ? ? ? 考虑多线程、无锁编程;

? ? ? ? 减少系统调用;

? ? ? ? 减少内存的分配释放:内存池、共享内存

? ? ? ? 持久连接等;

? ? 2、横向扩展,增加机器数量,分布式架构;

? ? # 线程池

? ? 使用不当会导致OOM,建议使用自定义线程池ThreadPoolExcutor。

? ? Executors有些参数设置不合理,newFixedThreadPool、newSingleThreadExecutor:队列无限制;而newCachedThreadPool:最大线程数Integer.MAX_VALUE,无限制;

? ? # ThreadLocal

? ? 使用场景:线程需要有自己单独的实例,该实例要在多个方法中共享,但不与其他线程共享,跟其他线程隔离。

? ? ? ? 如:上下文context信息。

? ? ? ? spring事物管理器,每个线程在threadLocal存储自己的connection信息。

? ? 底层原理:每个线程自己维护一个ThreadLocalMap,可以用多个threadLocal存放不同型的对象。

? ? ? ? ThreadLocalMap并未实现Map接口,不存在链表,通过数组方式,hash冲突时便需找下一空位置。

? ? ? ? ThreadLocalMap,对其key(threadLocal对象)的引用为弱引用方式,则当threadLocal对象只被threadLocalMap引用时,在下一次gc会被回收。

? ? ? ? 而threadlocalmap对value为强引用,如果线程一直运行,map中key为null,则value移除不了造成内存泄漏。

? ? ? ? 因此,在threadLocal使用完毕后要执行remove方法清除。

? ? ? ? 如果key为强引用,当threadlocal对象不被使用,但还被map引用时无法回收,导致内存泄露。

? ? ? ? java8优化:当threadloca执行get()、set()、remove()方法时会清除掉threadlocalmap中所有key为null的value,利于内存回收。

【Java容器类】

? ? # Collection

? ? ? ? # List、Set、Queue:

? ? ? ? ? ? ArrayList: 基于动态数组,初始对象为一个空数组。

? ? ? ? ? ? 当add时分配初始10个大小的内存。当满了之后,通过源码可以了解,通过grow方法扩容,扩容内存为当前的1.5倍。(为什么1.5倍,考虑方便移位操作,利用之前的内存)

? ? ? ? ? ? 扩容后的新数组,arrayCopy对之前数组进行拷贝。浅拷贝,只复制地址;

? ? ? ? ? ? 线程不安全,处理方法:

? ? ? ? ? ? 线程安全可用CopyOnWriteArrayList包装一下ArrayList。写入时先加锁,再copy一个新容器,在新容器里写入,原容器的引用指向新容器。

? ? ? ? ? ? 也可用vector,通过在它的每个方法都加了synchronized关键字,过于影响性能。

? ? ? ? 【Deque】是Queue的继承接口,实现类LinkedList、ArrayDeque,实现了队列和栈的功能;

? ? ? ? Stack是一个类,Vector的子类,基于数组实现,效率低,可使用Deque: push压栈、pop出栈并返回元素、peek返回栈顶元素不移除;

? ? ? ? ? ? 初始化:Deque<E> stack = new LinkedList<E>();

? ? ? ? Queue是接口,实现类LinkedList、PriorityQueue: add、offer进队,remove、poll出队,peek获取队头元素不删除;

? ? ? ? ? ? 初始化 Queue<E> queue = new LinkedList<E>();

? ? ? ? ? ? ? ? ? Deque<E> queue = new LinkedList<E>();

? ? # Map

? ? ? ? HashMap:数组+链表/红黑树

? ? ? ? 可以允许key有一个null;在数组首位;

? ? ? ? 扩容:初始插入时扩容16个初始值,后续超过阈值(当前容量*0.75)时扩容2倍重新rehash;扩容2倍方便rehash时元素迁移(按位与hash),2的次幂会散裂更均匀,减少碰撞;

? ? ? ? equals方法与hashcode方法:Object类中,equals方法和==方法一致,比较对象地址来判断是不是同一对象,设计equals方法是为了重写;如String类便是重写了equals方法来判断字符串相等;

? ? ? ? 重写equals方法必须要同时重写hashcode方法,为了提高比较性能,先去判断hashcode再去执行equals方法比较。

? ? ? ? ConcurrentHashMap:1.7分段锁实现并发安全。1.8 synchornized+CAS。因为锁粒度降低,在粗粒度里reentrantLock的condition来控制粒度边界会更灵活。粒度小时,synchronized不比它差。

? ? ? ? put:key对应的数组元素为null->CAS设置当前值;不为null时,synchronized加锁put链表操作;

? ? ? ? 读:用volitile来修饰数组、node节点中value、下一节点的引用next,来保障可见性;

? ? ? ? concurrentHashMap不允许为null,源码在put时会先校验key value是否为null;

? ? ? ? 因为二义性不能保障线程安全,不存在key时,get方法得到null(不知是不存在还是值为null),这时put一个null时,contains方法结果又是true,结果不一致,线程不安全。

? ? ? ? 为什么使用红黑树:红黑树不是绝对的平衡,做到近似平衡,局部平衡,而平衡二叉树AVL追求绝对平衡,查找效率差别不大,avl略高些,AVL在频繁插入删除时为了维持高度平衡代价更多,调整次数更多。所以红黑树插入效率更高。

【JVM】

? ? # 垃圾回收机制

? ? ? ? 可达性分析,判断对象是否可回收;

? ? ? ? 可作为可达性分析的GC Roots: 栈中引用的对象;方法区中类静态属性及常量所引用的对象;

? ? ? # 分代思想

? ? ? ? 年轻代

? ? ? ? ? ? Eden : fromS0 : toS1 = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 );

? ? ? ? ? ? 采用标记-复制回收(存活率低)

? ? ? ? 老年代

? ? ? ? ? ? 标记-清除或标记-整理回收;

? ? ? ? 永久代(元空间)(方法区):

? ? ? ? ? ? java8之后取消了永久代,元空间取而代之;

? ? ? ? ? ? 之前永久代与堆空间连续,老年代GC时会同时GC永久代;现元空间存在于本地内存,不会受老年代GC影响;避免OOM异常;空间由系统内存来控制;

? ? ? ? 默认年轻代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 )

? ? ? ? 年轻代对象进入老年代:根据存活时间(经过eden区垃圾回收次数,默认存活15次);对象占用内存非常大的直接分配老年代(因为会导致新生代垃圾回收的复制算法效率低下)

? ? ? ? # 垃圾回收器组合

? ? ? ? ? ? 年轻代ParallelGC(标记复制)————老年代CMS(标记-清除)

? ? ? ? ? ? 年轻代G1————老年代G1? G1:整体标记-整理,局部Region标记复制

? ? # JVM参数调优

? ? ? ? # JVM参数

? ? ? ? -Xms? ? 初始堆大小

? ? ? ? -Xmx? ? 最大堆大小

? ? ? ? -Xmn? ? 新生代大小,通常为最大堆内存的1/3或1/4;

? ? ? ? -Xss? ? 线程堆栈大小,默认1M

? ? ? ? -XX:NewRatio? ? 新生代与老年代比例,默认=2

? ? ? ? -XX:SurvivorRatio? Eden区与Suvivor区比例,默认8

? ? ? ? -XX:PermSize? ? 永久代(方法区)初始大小

? ? ? ? -XX:MaxPermSize? ? 永久代(方法区)最大值

? ? ? ? -XX:+PrintGCDetails? 打印GC详情

? ? ? ? -XX:+HeapDumpOnOutOfMemoryError? OOM时Dump出当前堆栈快照

? ? ? ? # 调优目标

? ? ? ? 堆内存使用率<=70%;

? ? ? ? 老年代内存使用率<=70%;

? ? ? ? Full GC次数0,或平均Full GC间隔时间够大(>=24小时);

? ? ? ? # 触发Full GC的场景及优化应对:

? ? ? ? ? ? 老年代空间不足,晋升到老年代的对象大于老年代可用空间:让对象在Minor GC阶段被回收,不要创建过大对象,因为过大对象创建时会直接进入老年代;

? ? ? ? ? ? 通过dumpheap分析是否存在内存泄露;

? ? # 问题排查

? ? ? ? 系统缓慢、CPU100%、大量告警

? ? ? ? ? ? 1、top查看CPU过高的进程;

? ? ? ? ? ? 2、top -Hp查看哪些线程CPU过高;

? ? ? ? ? ? 3、根据jstack命令查看当前线程的堆栈信息;(线程id要先转成16进制;jstack PID|grep -C N nid)

? ? ? ? ? ? 4、根据堆栈信息可分析CPU过高原因:由于频繁的垃圾回收、代码耗时计算、死锁等;

? ? ? ? Full GC频繁:

? ? ? ? jstat -gcutil 查看GC发生时间和次数

? ? ? ? jmap导出内存日志,可用eclipse的mat工具分析哪些对象消耗内存;

? ? ? ? 根据GC日志(-XX:+PrintGCDetails)分析Full GC前后各区内存情况,分析是否因为哪个区内存空间小导致Full GC,适当调整;

? ? ? ? jmap -heap pid :查看整体堆使用信息

? ? ? ? jmap -histo pid :查看实例数量和占用空间大小

? ? ? ? ‐XX:+HeapDumpOnOutOfMemoryError 运行时内存溢出导出到dump文件

【类加载与反射机制】

? ? 加载-链接(解析、验证)-初始化

? ? 程序运行时将类的.class文件(磁盘)加载到java运行内存(元空间),将字节码结构转换为运行时结构,并创建一个class对象;

? ? 双亲委派加载:应用程序类加载器(Application ClassLoader)——扩展类加载器(Extension ClassLoader)——启动类加载器(Bootstrap ClassLoader)

? ? 反射:运行时可动态加载任一类,获取class对象的基本信息;

? ? spring中通过反射实例化创建bean;

【网络通信相关】

? ? ISO七层模型:应用层(http,smtp)、表示层、会话层、传输层(TCP、UDP)、网络层(IP)、数据链路层、物理层

? ? TCP和UDP区别:

? ? ? ? TCP:面向连接;可靠传输;流量和拥塞控制(具有窗口);一对一;

? ? ? ? UDP:无连接;不保证可靠交付;无流量控制;一对一,一对多,多对多;

? ? TCP:三次握手,确认连接和序列号;

? ? ? ? 四次挥手,服务端的确认和发送关闭请求分两次发;因为服务端收到关闭请求后不能立即发送关闭请求,只能先发送收到确认,等待服务端所有报文发送完毕再发送关闭请求;

? ? ? ? 挥手客户端等待2ms关闭机制;确保服务端的没收到关闭确认重试可以收到,可靠关闭;

? ? HTTPS:安全;密文传输;需要证书;端口443

? ? ? ? https流程:数字证书、公钥、私钥、对称加密、非对称加密;

? ? ? ? ? ? 服务端拥有证书(包含公钥、证书失效日期)、私钥;

? ? ? ? ? ? 客户端请求获取证书,并根据公钥生成对称私钥,利用公钥加密发送给服务端;

? ? ? ? ? ? 服务端利用之前的私钥进行非对称解密,获取客户端私钥,然后进行对称加密传输;之所以不用非对称加密传输,考虑加解密效率问题;


https://www.xamrdz.com/backend/34z1923418.html

相关文章: