正文
双重检查锁定:
public class Singleton {
privatestaticvolatile Singleton instance; // 使用 volatile 禁止指令重排
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // 第一次检查,不加锁
synchronized (Singleton.class) { // 仅在第一次创建时加锁
if (instance == null) { // 第二次检查,避免多线程重复创建
instance = new Singleton();
}
}
}
return instance;
}
}
-
volatile
关键字确保变量的可见性和禁止指令重排(防止半初始化对象被使用)。
-
双重检查:外层检查避免已创建实例时的锁竞争,内层检查确保多线程安全。
枚举实现:
public enum Singleton {
INSTANCE; // 枚举实例,全局唯一
// 可以添加方法
public void doSomething() {
System.out.println("单例方法被调用");
}
}
实现代码简单,也是线程安全的。
饿汉式:
public class Singleton {
// 类加载时就创建实例(不管是否使用)
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE; // 直接返回已创建的实例
}
}
JVM 保证类加载时只创建一个实例,所以是线程安全的。
3. 面向对象的特征有哪些?
Java面向对象的三大特性包括:
封装、继承、多态
:
-
封装
:封装是指将对象的属性(数据)和行为(方法)结合在一起,对外隐藏对象的内部细节,仅通过对象提供的接口与外界交互。封装的目的是增强安全性和简化编程,使得对象更加独立。
-
继承
:继承是一种可以使得子类自动共享父类数据结构和方法的机制。它是代码复用的重要手段,通过继承可以建立类与类之间的层次关系,使得结构更加清晰。
-
多态
:多态是指允许不同类的对象对同一消息作出响应。即同一个接口,使用不同的实例而执行不同操作。多态性可以分为编译时多态(重载)和运行时多态(重写)。它使得程序具有良好的灵活性和扩展性。
4. hashmap 扩容原理是什么?
hashMap默认的负载因子是0.75,即如果hashmap中的元素个数超过了总容量75%,则会触发扩容,扩容分为两个步骤: