Java 系统知识 ¶
约 2317 个字 预计阅读时间 8 分钟
Abstract
准备面试时稍微学习的一些零散知识
(不用 java,也不喜欢 java,但还是记录一下吧
线性池 ¶
- 线性池的原因
- 不断的创建和删线程,会带来较大的系统资源负载
- 线程缺乏统一的管理,可能会带来无限制的创建线程
- 线程之间抢占资源
- 线程池的属性
- 核心线程数:保持存在的线程数量,这些线程会一直存在,不会被删除
- 任务缓冲锐裂:当所有的核心线程都在运行时,新的任务会被加入到缓冲队列中
- 非核心线程数:当任务缓冲队列满后,将会创建新的线程来执行队列中的任务,且额外创建的线程数不会超过非核心线程数
- 空闲线程的存活时间:当非核心线程空闲时,且持续了一段时间后,此线程将会被删除
- 拒绝策略,当非核心线程和任务缓存队列满后,对待新的任务的策略
- Java 默认的线程池类型
名称 | 核心线程数 | 线程池大小 | 非核心线程存活时间 | 等待队列大小 |
---|---|---|---|---|
CachedThreadPool | 0 | ∞ | 60s | 0 |
SingleThreadExecutor | 1 | 1 | 0 | ∞ |
FixedThreadPool | n | n | 0 | ∞ |
ScheduledThreadPoolExecutor |
- Java 默认的线程池有什么问题,为什么会引起 OOM 异常(OutOfMemoryError)
- CachedThreadPool 允许创建无线的线程,从而引起 OOM 异常
- SingleThreadExecutor 和 FixedThreadPool 请求队列为无限长,可能会堆积大量的消息,从而引发 OOM 异常。
Java 内存 ¶
- 内存类型
- 主内存:线程之间共享的变量储存在主内存中
- 本地内存:每个线程独立拥有的内存
- 本地内存保存的是主内存的共享变量的副本
- 垃圾回收
- 根搜索算法(可达性分析算法)从 GC ROOT 结点沿着引用链搜索,无法到达的结点即为不可到达的对象
- 垃圾回收器
- G1 收集器
- 独特的分代垃圾回收器,分代 GC:分代收集器,同时兼顾年轻代和老年代
- 使用分区算法,不要求 eden,年轻代或老年代的空间都连续
- 并行性:回收期间,可由多个线程同时工作,有效利用多核 CPU 资源
- 空间整理:回收过程中,会进行适当对象移动,减少空间碎片
- 可预见性:G1 可选取部分区域进行回收,可见缩小回收范围,减少全局停顿
- G1 收集器的过程
- 初始标记(它标记了从 GC ROOT 开始直接可达的对象)Stop-The-World
- 并发标记(从 GC Roots 开始对堆中对象进行可达性分析,找出存活对象)
- 最终标记(标记那些在并发标记阶段发生变化的对象,将被回收)Stop-The-World
- 筛选回收(首先对各个 Regin 的回收价值和成本进行排序,根据用户所期待的 GC 停顿时间指定回收计划,回收一部分 Region)Stop-The-World
- G1 收集器
Map¶
- HashMap 的结构
- 采用链地址法,当发生哈希冲突时使用链表解决
- 当链表过长时,在 JDK1.8 下采用红黑树代替链表,当数据量较少时,转回链表
- 当存储的数据量超过一个阈值后,HashMap 的哈希表长度将会扩容到原来的两倍,然后将所有的数据重新分配到新的内存中
- HashMap 这样扩容的原因
- 通过恰好两倍扩容,可以让原来在第 i 个链表的值被恰好分配到第 i 和第 2i 个链表的位置
- 每一个值,只需要判断其哈希值在某个二进制位上的值即可直接完成分配
- TreeMap 的结构
- TreeMap 是一颗红黑树
设计模式 ¶
- 设计原则
- 开闭原则:对扩展开放,对修改关闭
- 里氏替换原则:子类必须拥有所有的父类功能,子类可以开发自己的新功能
- 依赖倒置原则:高层实现不能依赖低层实现,而是依赖于低层的抽象类
- 单一职责原则:一个类应当只负责一个职责
- 接口隔离原则:接口应该更小更具体,而不是去实现很庞大的借口来适应所有需求
- 迪米特法则:避免与无关实体进行通信
- 合成复用原则:尽量先使用组合或者聚合等关联,其次考虑继承
- 设计模式
- 创建型模式
- 单例模式:限制一个类只能有一个实例
- 原型模式:以一个此类型的实例为模版,通过拷贝内存中的二进制值来直接创建一个对象
- 工厂模式:将创建对象的过程由另一个类进行封装
- 建造者模式:将一个复杂的对象分为多个简单的对象的组合,并实现将多个小对象进行拼装的过程
- 结构型模式
- 代理模式:使得两个对象之间不能直接引用访问,只能通过第三方,可以保护目标对象,扩展目标对象的功能
- 适配器模式:将一个类的接口转换为另一个类的借口,通常是为了适配两个接口的对接问题
- 桥接模式:将抽象与实现分离,使得他们可以独立变化,用组合关系来代替继承关系
- 装饰器模式:为类增加新的功能的同时,避免了继承
- 外观模式:隐藏系统的复杂性
- 享元模式:重复 使用已经创建的同类对象
- 组合模式
- 创建型模式
- 行为型模式
- 模板方法模式:仅实现一个操作中的骨干步骤,具体步骤由其子类实现
- 策略模式
- 命令模式
- 责任链模式
- 状态模式
- 观察者模式
- 中介者模式
- 迭代器模式
- 访问者模式
- 备忘录模式
- 解释器模式
String¶
- String 类型
- String 类型是不可变的,对 String 类型进行操作时,会重新生成新的 String 对象
- StringBuilder 和 StringBuffer
- StringBuilder 和 StringBuffer 都是可变的
- StringBuilder 没有线程同步,存在线程安全问题,但是其效率略高于 StringBuffer
- StringBuffer 能够保证线程安全,但效率较低
接口和抽象类 ¶
- 接口和抽象类的区别
- 抽象类可以写非抽象方法,而接口类只能有抽象方法
- 一个类只能继承自一个抽象类,而一个类能实现多个接口
- 继承是一个“是不是”的关系,而接口实现则是“有没有”的关系
构造函数 ¶
- 子类实例化总是默认调用父类的无参构造方法
- 为了让父类初始化属性和方法
equals¶
equals
和==
的区别==
对于基本类型时,比较的是两个对象的值是否相同,而对于对象时,则比较的是这两个引用是否指向了同一个对象equals
则可以由此类进行重写,使得其满足正常的比较关系。若不进行重写,则与==
等价
equals
和hashCode
为什么需要同时进行重写hashCode
在Object
类下的默认行为是将此值的地址取出作为hashCode
,但这与hashCode
本意不同,hashCode
的值应当满足对于任意 x 若x.equals(y) = true
,则x.hashCode() = y.hashCode()
,所以当重写equals
时,通常意味着这个值的相等概念与==
不同。所以必然需要重写hashCode
避免在hashMap
中出现意料之外的情况
CopyOnWrite¶
写入时复制(CopyOnWrite,简称 COW)思想是计算机程序设计领域中的一种通用优化策略。其核心思想是,如果有多个调用者(Callers)同时访问相同的资源(如内存或者是磁盘上的数据存储
通俗易懂的讲,写入时复制技术就是不同进程在访问同一资源的时候,只有更新操作,才会去复制一份新的数据并更新替换,否则都是访问同一个资源。
JDK 的 CopyOnWriteArrayList/CopyOnWriteArraySet 容器正是采用了 COW 思想,它是如何工作的呢?简单来说,就是平时查询的时候,都不需要加锁,随便访问,只有在更新的时候,才会从原来的数据复制一个副本出来,然后修改这个副本,最后把原数据替换成当前的副本。修改操作的同时,读操作不会被阻塞,而是继续读取旧的数据。这点要跟读写锁区分一下。
最后更新:
2023年10月8日 15:31:56
创建日期: 2023年9月6日 10:51:03
创建日期: 2023年9月6日 10:51:03