目录
前言
“实战面经”是本专栏的第二个部分,本篇博文是第十篇博文,如有需要,可:
一、TCP报头中都有什么,UDP报头中都有什么?
- TCP: 源端口、目标端口、序号、确认号、校验和、SYN、ACK、FIN等标志位
- UDP: 源端口、目标端口、校验和、数据长度
二、单例模式的各种实现
- 惰性加载:
1) Double-Check: 不直接在getInstance方法上加synchronized,而是先Check要不要加锁,是为了避免线程一进来就加锁,产生较大的性能消耗。
2) 静态内部类法: 静态内部类在外部类加载时不会被加载,被调用时加载。
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
- 饿汉加载——枚举实现:
1) 可以避免反射攻击: Constructor类的newInstance中对修饰符进行了判断, 被enum修饰的类不允许实例化。
2) 避免序列化问题: readObject会返回一个新的对象,而枚举类型通过valueOf 来查找枚举对象。
3) 线程安全: 当一个Java类第一次被真正使用到的时候静态资源被初始化,Java 类的加载和初始化过程都是线程安全的。所以,创建一个enum类型是线程安全的。
public enum Singleton {
INSTANCE;
public Singleton getInstance() {
return INSTANCE;
}
}
三、非静态内部类持有外部类的引用造成内存泄露的问题
-
原因: 由于非静态内部类持有外部类的引用,造成外部类的实例无法被回收,导致内存泄漏。
-
解决方法: 改成静态内部类,静态内部类调用外部类的对象,直接从方法区中获得引用。
四、JDBC、Tomcat为什么要破坏双亲委派模型?
-
JDBC: DriverManager 类中要加载各个实现了Driver接口的类,然后进行管理,但是DriverManager位于 JAVA_HOME中jre/lib/rt.jar 包,由BootStrap类加载器加载,而其Driver接口的实现类是位于服务商提供的 Jar 包,需要由子类加载器去加载Driver实现,这就破坏了双亲委派模型。
-
Tomcat:
1) 对于各个 webapp中的 class和 lib,需要相互隔离,不能出现一个应用中加 载的类库会影响另一个应用的情况,而对于许多应用,需要有共享的lib以便不浪费 资源。
2) 与 jvm一样的安全性问题。使用单独的 classloader去装载 tomcat自身的类 库,以免其他恶意或无意的破坏。
3) 热部署, tomcat修改文件不用重启就自动重新装载类库。
五、如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?
使用Bloom Filter
- 原理: 在一个比较大的范围,如Integer的非负范围[0, 2147483647],计算哈希值,用一个01数组来存储,第i位有就是1,没有就是0.
- 缺点: 因为存在哈希冲突的可能,所以不存在是绝对准确的,存在不一定准确。
- 解决方案: 多重哈希
六、B extends A时,类中的代码加载关系
- 父类静态代码块
- 子类静态代码块
- 父类构造方法
- 子类构造方法
七、ceil、floor、round方法的作用
ceil
: 天花板,向上取整floor
: 地板,向下取整round
: 四舍五入
八、Spring依赖注入的几个注解
-
@Autowired
: Spring注解,默认byType
,需要byName
时可以配合@Qualifier
,即@Qualifier("bean")
. -
@Resource
:javax.annotation
包下的注解,默认byName
,即@Resource(name="bean")
.
九、数据库乐观锁的实现
数据库的乐观锁实现方式是使用版本号机制。当读取数据时,将version
字段的值一同读出,数据每更新一次,对此version
值加一。当我们提交更新的时候,判断当前版本信息与第一次取出来的版本值大小,如果数据库表当前版本号与第一次取出来的version
值相等,则予以更新,否则认为是过期数据,拒绝更新,让用户重新操作。
后记
这篇面经里的考点比较浅也比较少。