单例模式(懒汉、饿汉、同步锁、static、枚举)实现

时间:2021-04-05 14:33:00

使用前提:

  需要频繁的进行创建和销毁的对象,创建对象时耗时过多或耗费资源过多

三要素:

  • 1、构造方法私有化;
  • 2、实例化的变量引用私有化;
  • 3、获取实例的方法共有。

1.饿汉式单例

  弊端:在类装载的时候就完成实例化

/**
* 饿汉式单例
*
* @author Wonder
* @history create Wonder 2018年10月24日 上午9:55:32
* @version 1.0
*/
public class Singleton1 {
private Singleton1() {
}// 1私有化构造 private final static Singleton1 singleton1 = new Singleton1();// 2实例化 public static Singleton1 getInstance() {// 3对外提供
return singleton1;
} }

2.懒汉式单例

  弊端:多线程环境下会产生多个single对象,线程不安全

/**
* 懒汉式单例
* 多线程环境下会产生多个single对象
*
* @author Wonder
* @history create Wonder 2018年10月24日 上午10:17:59
* @version 1.0
*/
public class Singleton2 {
private Singleton2() {
}// 1私有化构造 private static Singleton2 singleton2 = null;// 延迟实例 public static Singleton2 getInstance() {
if (singleton2 == null) {
singleton2 = new Singleton2();
}
return singleton2;
}
}

3.懒汉式单例(synchronized同步锁)

  弊端:效率低

    同步方法的方式:获取实例时,每次都要执行同步方法,效率太低

    同步代码块的方式:可能多个线程同时进入if判断,实际页无法起到线程同步的作用

/**
* 懒汉式单例 只对需要锁的代码部分加锁
*
* @author Wonder
* @history create Wonder 2018年10月24日 上午10:17:59
* @version 1.0
*/
public class Singleton4 {
private Singleton4() {
}// 1私有化构造 private static Singleton4 single = null;// 延迟实例 public static Singleton4 getInstance() {
if (single == null) {
synchronized (Singleton4.class) {
single = new Singleton4();
}
}
return single;
}
}

4.双重检查

  1.使用volatile关键字,防止防止 JVM 进行指令重排优化

  2.进行了两次if (singleton == null)检查,如果为null,同步代码块,创建实例,否则直接返回singleton实例

public class Singleton {

    private static volatile Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

5.静态代码块和静态内部类

  静态代码块的方式

public class Singleton5 {
private Singleton5() {
}// 1私有化构造 private static Singleton5 single = null;// 延迟实例 // static静态代码块
static {
single = new Singleton5();
} public static Singleton5 getInstance() {
return single;
}
}

  静态内部类方式更优(懒加载)

    静态内部类方式在Singleton类被装载时并不会立即实例化

public class Singleton {

    private Singleton() {}

    private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
} public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}

6.枚举实现

  简单枚举方式:

public enum Singleton {
INSTANCE;
public void whateverMethod() { }
}

  优化:内部枚举类

public class SingletonFactory {

    // 内部枚举类
private enum EnmuSingleton {
SINGLETON;
private Singleton6 single; // 枚举类的构造方法在类加载是被实例化
private EnmuSingleton() {
single = new Singleton6();
} public Singleton6 getInstance() {
return single;
} } public static Singleton6 getInstance() {
return EnmuSingleton.SINGLETON.getInstance();
}
} class Singleton6 {
public Singleton6() {
}
}