饿汉式
饿汉式:类加载的时候就把类实例化了。
饿汉式-静态成员变量
public class Singleton1 {
public static Singleton1 instance = new Singleton1();
public static Singleton1 getInstance() {
return instance;
}
private Singleton1(){
}
}
饿汉式-静态代码块
public class Singleton2 {
public static Singleton2 instance;
private Singleton2(){
}
/**
* 静态代码块
*/
static {
instance = new Singleton2();
}
public static Singleton2 getInstance() {
return instance;
}
}
静态代码块在类加载的时候加载,静态代码块比构造先加载。
懒汉式
类不预先加载,在调用相应方法的时候才去加载。
懒汉式 - 单重检查,线程不安全
public class Singleton3 {
private static Singtelon3 instance;
//私有化构造方法
private Singleton3{
}
public static Singleton3 getInstance() {
if (instance == null){
instance = new Singleton3();
}
return instance;
}
}
懒汉式 - 方法级别加锁
public class Singleton4 {
//valatile关键字能使的该属性在线程间共享,同时能静止指令重排序
public static volatile Singleton4 instance;
//私有化构造方法
private Sing(){}
public static synchronized Singleton4 getInstance() {
if (instance == null) {
instance = new Singleton4();
}
return instance;
}
方法层面上加锁,它的效率很慢。
懒汉式 - 双重检查
public class Singleton5 {
public static volatile Singleton4 instance;
private Singleton5() {}
public static Singleton5 getInstance() {
if (instance == null) {
//只有一个线程进入
synchronized(Singleton5.class) {
// 判断其他线程是否已经创建了实例
if (instance == null) {
instance = new Singleton5();
}
}
}
return instance;
}
}
第一层判断可能会有多个线程在未创建出实例时进入,加锁只让一个线程去创建,这时还有其他线程已经进入去获取锁,但是第二层检查,发现已经创建就不再创建,直接返回。
懒汉式 - 静态内部类方式
public class Singleton7 {
private Singleton7() {}
//静态内部类
private static class SingletonHolder {
private static final Singleton7 INSTANCE = new Singleton();
}
public static Singleton7 getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举方式 - 也是饿汉式
public enum Singleton6 {
//枚举使用了该类的默认构造,如果重写了构造,枚举使用的就是重写后的构造。
//默认构造
SINGLETON_6;
}
可能存在的问题
- 除枚举方式外,其他方式通过序列化和反序列化会破坏单例模式。