单例模式详解

一.单例模式的特点
  1.保证JVM内存中只有一对象实例,且实例只能被创建一次.
  2.对象实例只能由单例类自身创建,不能由其他对象创建.
  3.没有接口,不能被继承.

二.使用场景
  1.创建应用中的全局对象.
  2.WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来.
  3.创建新建时占用资源多且可重复使用的对象,如I/O连接,数据库连接等.

三.实现方式

  1.饿汉模式 

/**
 * @date 2020-6-11
 * @description 饿汉模式
 * 特点:
 * 1.在类加载的时候就创建实例,即使不被使用,仍旧存在实例,所以会产生垃圾对象
 * 2.线程安全
 */
public class SingleDemo1 {
    private static SingleDemo1 singleDemo1 = new SingleDemo1();
    private SingleDemo1() {}
    public static SingleDemo1 getInstance() {
        return singleDemo1;
    }
}

  2.懒汉模式

/**
 * @date 2020-6-11
 * @description 懒汉模式
 * 特点:
 * 1.在调用实例获取方法的时候创建实例
 * 2.线程不安全,并发调用实例获取方法时,可能或导致重复创建
 */
public class SingleDemo2 {
    private static SingleDemo2 instance = null;
    private SingleDemo2() {}
    public static SingleDemo2 getInstance() {
        if(instance == null) {
            instance = new SingleDemo2();
        }
        return instance;
    }
}

  3.volatile和双重检测的懒汉式

/**
 * @date 2020-6-11
 * @description volatile + 双重检测的懒汉式
 * 特点:
 * 1.依旧采用懒加载方式获取实例
 * 2.使用volatile修饰成员变量,保证成员变量并发下的线程可见性,同时防止CPU进行指令重排
 * 3.使用synchronized加锁,保证并发下只有一个线程可以创建实例
 * 4.线程安全
 */
public class SingleDemo3 {
    private volatile static SingleDemo3 instance = null;
    private SingleDemo3() {}
    public static SingleDemo3 getInstance() {
        if(instance == null) {
            synchronized (SingleDemo3.class) {
                if(instance == null) {
                    instance = new SingleDemo3();
                }
            }
        }
        return instance;
    }
}

  4.枚举方式

/**
 * @date 2020-6-11
 * @description 枚举方式
 * 1.在JVM只会初始化一次,枚举本身创建就是单例的
 * 2.线程安全
 * 3.自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
 * 4.Effective Java作者Josh Bloch推荐创建方法
 */
public class SingleDemo4 {
    private SingleDemo4() {}
    public static SingleDemo4 getInstance() {
        return SingleEnum.INSTANCE.getSingleDemo4();
    }

    private enum SingleEnum {
        INSTANCE;
        private SingleDemo4 singleDemo4;
        SingleEnum() {
            singleDemo4 = new SingleDemo4();
        }
        public SingleDemo4 getSingleDemo4() {
            return singleDemo4;
        }
    }
}

  5.静态内部类方式

/**
 * @date 2020-6-11
 * @description 静态内部类方式
 * 特点:
 * 1.利用了静态内部类的类加载机制,类只能被加载一次
 * 2.线程安全
 * 3.实现懒加载
 * 静态内部类类加载说明:
 * 1.JVM中,无论是外部类还是内部类或是静态内部类都只能被加载一次.
 * 2.外部类在加载时,首先会依次初始化静态变量,静态代码块,静态方法,但不会加载内部类或是静态内部类.
 * 3.静态内部类在被调用时才会加载,且只加载一次.
 * 4.外部类和静态内部类的加载是分开的,加载不会相互影响.
 */
public class SingleDemo5 {
   private static class SingletonHolder {
       public static final SingleDemo5 INSTANCE = new SingleDemo5();
   }
   private SingleDemo5 (){}
   public static final SingleDemo5 getInstance() {
       return SingletonHolder.INSTANCE;
   }
}
原文地址:https://www.cnblogs.com/zhexuejun/p/13093372.html