定义:“一个类仅有一个实例,并且自行实例化向整个系统提供”
(1)构造器私有化,防止外界通过调用构造方法实例化对象。
(2)提供一个公有的静态方法,只有通过该类提供的静态方法才能得到该类的唯一实例
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:12:44
* @JDK versions: 1.8.0_101
*/
public class Singleton {
private final static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
//...
}
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
缺点:由于在类装载的时候就完成实例化。所以在程序运行时如果从始至终从未使用过这个实例,则会造成内存的浪费。
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:12:56
* @JDK versions: 1.8.0_101
*/
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
//...
}
优点:实现了延迟加载,避免了内存的浪费
缺点:线程不安全。在多线程下两个线程同时通过了if判断,则会产生多个实例。所以并不推荐使用
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:13:04
* @JDK versions: 1.8.0_101
*/
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
//...
}
优点:延迟加载且线程安全
缺点:效率低下,每个线程想获得类的实例时,不论是否初始化都要进行同步,不推荐使用
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:13:15
* @JDK versions: 1.8.0_101
*/
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
//...
}
优点:延迟加载,且效率高。
缺点:指令重排序导致多线程访问时获得没初始化的对象,所以不推荐使用
创建一个对象的正常过程为:①分配对象内存空间->②初始化对象->③设置引用指向内存空间。但是jvm会做出优化将②和③的执行次序交换。下面我们用A和B来模拟两个线程的执行情况
时间 | 线程A | 线程B |
t1 | A1: 分配对象的内存空间 | |
t2 | A3:设置instance指向内存空间 | |
t3 | B1:判断instance是否为null | |
t4 | B2:由于instance不为null,线程B将访问instance引用的对象 | |
t5 | A2:初始化对象 | |
t6 | A4:访问instance引用对象 |
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:13:15
* @JDK versions: 1.8.0_101
*/
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
//...
}
延迟加载,且效率高。且解决了指令重排序的问题,可以使用
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:13:41
* @JDK versions: 1.8.0_101
*/
public class Singleton {
private Singleton(){}
private static class SingletonHolder{
private static final Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.SINGLETON;
}
//...
}
静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonHolder类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。这一技术是被JVM明确说明了的,因此不存在任何二义性。
/**
* @Created with IDEA
* @author:Dick_YangDi
* @Date:2018/4/24
* @Time:13:45
* @JDK versions: 1.8.0_101
*/
public enum Singleton {
INSTANCE;
private Singleton() {}
}
功能完整,使用简洁、无常提供了序列化,还可以防止反射攻击,单元素的枚举类型是实现单例模式的最佳方法