参考文章:
https://blog.csdn.net/u014672511/article/details/79774847
https://www.cnblogs.com/dongyu666/p/6971783.html
模式 | 描述 | 优点 | 缺点 | 备注 |
懒汉式 | 用到时才加载 | 不浪费内存 | 线程不安全 |
|
饿汉式 | 在加载类的时候已经加载 | 立即加载 | 占用资源 | 适用于占用内存较少的资源 |
双重校验锁 | 双重非空校验,线程安全,防止重排 | 线程结合单例的最优解 |
| Spring源码用此方法 |
静态内部类 | 是靠JVM保证类的静态成员只能被加载一次的特点,这样就从JVM层面保证了只会有一个实例对象
|
|
|
|
静态代码块 | 也是一种饿汉模式
|
|
|
|
枚举 | 自由序列化,线程安全,保证单例
|
|
|
|
懒汉式:
/**
* 懒汉式
* 这种写法能够很好的在多线程中工作,而且看起来具备很好的lazy loading,但是,遗憾的是,效率很低,99%的情况下不需要同步
* 线程不安全
* @author Administrator
*
*/
public class SingletonLazy1 {
private static SingletonLazy1 instance;
private SingletonLazy1 singleton;
private SingletonLazy1() {}
public static SingletonLazy1 getSingleton(SingletonLazy1 instance) {
if(instance == null) {
return new SingletonLazy1();
}
return instance;
}
}
饿汉式:
/**
* 饿汉模式
* 这种方法基于classloader机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装在的
* 原因有很多,在单例模式中大多都是调用getInstance方法,但是也不确定其他方式(或者其他静态方式)导致类装载
* 这个时候初始化instance显然没有达到lazy loading效果
* @author Administrator
*
*/
public class SingletonHungry {
private static SingletonHungry instance = new SingletonHungry();
//将构造器设置为private禁止通过new进行实例化
private SingletonHungry() {}
public static SingletonHungry getInstance(SingletonHungry instance) {
return instance;
}
}
双重校验锁:
//单例模式的懒汉实现5--线程安全
//通过设置同步代码块,使用DCL双检查锁机制
//使用双检查锁机制成功的解决了单例模式的懒汉实现的线程不安全问题和效率问题
//DCL 也是大多数多线程结合单例模式使用的解决方案
public class SingletonLazy5 {
private static volatile SingletonLazy5 instance;
private SingletonLazy5 singleton;
private SingletonLazy5() {}
public static synchronized SingletonLazy5 getSingleton(SingletonLazy5 instance) {
try {
if (null == instance) {
// 模拟在创建对象之前做一些准备工作
Thread.sleep(1000);
synchronized (SingletonLazy5.class) {
if(null == instance) {
instance = new SingletonLazy5();
}
}
}
} catch (InterruptedException e) {
}
return instance;
}
}
静态内部类:
/**
* 静态内部类方法
* 线程安全:是靠JVM保证类的静态成员只能被加载一次的特点,这样就从JVM层面保证了只会有一个实例对象
*
*/
public class SingletonStaticClass {
public static class SingletonHolder{
private static SingletonStaticClass singleton = new SingletonStaticClass();
}
private SingletonStaticClass() {}
private static SingletonStaticClass getInstatnce() {
return SingletonHolder.singleton;
}
}
静态代码块
/**
* 静态代码块,也是一种饿汉模式
* @author Administrator
*
*/
public class SingletonStaticBlock {
private static SingletonStaticBlock singletonStaticBlock;
static {
singletonStaticBlock = new SingletonStaticBlock();
}
public static SingletonStaticBlock getInstance() {
return singletonStaticBlock;
}
}
枚举:
/**
* 枚举方法
* 用enum实现Singleton的三个特征:自由序列化,线程安全,保证单例
* 自由序列化:每一个枚举类型和枚举变量在JVM中都是唯一的,枚举的方法是被编译器禁用,保证调用时不破坏单例。
* 线程安全:enum类不能够被继承,是final类型的;类似饿汉模式,通过第一次调用时的静态初始化创建的对象是线程安全的。
* 保证单例:enum仅有一个private的构造器;枚举其实和使用静态内部类加载方法相似,另外,如果枚举一个实例,没有起到懒加载的作用
* @author Administrator
*
*/
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}