package com.test.mytest;
/**
* Created by wuzm on 2017/11/24.
*/
/**
* 单例模式
*/
public class Singleton1 {
private static Singleton1 singleton = null;
private Singleton1() {
}
/**
* 饱汉模式
* 等第一次使用的时候在初始化(已吃饱,等饿的时候再吃)--懒加载
* 优点:启动速度快,节省资源
* 缺点:线程不安全,存在竞态条件
*/
public static Singleton1 getInstance() {
if (singleton == null) {
singleton = new Singleton1();
}
return singleton;
}
/**
* 饱汉变种1,解决线程不安全问题
* 优点:绝对线程安全
* 缺点:并发性能极差,任何一个线程占用了getInstance_1方法时,别的线程都只能等待,其实已经沦为串行的了
*/
public synchronized static Singleton1 getInstance_1() {
if (singleton == null) {
singleton = new Singleton1();
}
return singleton;
}
/**
* 饱汉变种2:双重检查
* 即在变种1的基础上又套了一层check
* 优点:懒加载+线程安全
* 缺点:有可能得到半个对象?
* ----------------------------------------------------------------------------------------
* 解析:
* 假设有A,B两个线程,A获得同步锁,执行single=new Singleton1(),该行代码其中有以下3个步骤(执行无序):
* (1)memory=allocate();//为singleton对象分配内存
* (2)instance=memory;//注意现在instance是非空的,但还没初始化
* (3)ctorSingleton(instance);//调用singleton的构造函数,传递instance
* (4)连接引用和实例
* 当执行到instance=memory;时,线程B进入了第一次null判断,判断结果为非空,返回了instance,
* 但此时返回的不是单例的实例对象,而是内存对象
* -----------------------------------------------------------------------------------------
* 为什么要在synchronized里面再加一层if判断呢?
* -----------------------------------------------------------------------------------------
* 解析:
* 假设线程A,B同时执行到了synchronized,虽然只有一个线程能执行,假设A先执行,A执行完成后创建了一个实例
* 之后线程B获得了锁,但是此时没有检查singleton是否为空就直接执行了,所以还是会出现两个single实例的情况
*/
public static Singleton1 getInstance_2() {
if (singleton == null) {
synchronized (Singleton1.class){
if (singleton == null) {
singleton = new Singleton1();
}
}
}
return singleton;
}
/**
* 饱汉变种3:解决变种2中半个对象问题
* volatile:禁止指令重排序,保证内存可见性
* 禁止指令重排序:就是解决上面提到的返回内存对象问题
* private static volatile Singleton1 singleton = null;
* 还有一种方法可以不使用volatile达到同样的效果
* Singleton1 temp=new Singleton1();
* temp.toString();//构造与赋值之间随意做点事情保证顺序
* singleton=temp;
*/
private static final Singleton1 singleton1 = new Singleton1();
/**
* 饿汉模式
* 类加载时初始化单例,以后访问时直接返回
* 优点:天生的线程安全,得益于类加载机制
* 确定:资源浪费,万一单例没有用武之地
*/
public static Singleton1 getInstance_3() {
return singleton1;
}
/**
* Holder模式
* 既希望利用饿汉模式的有希望通过懒加载避免资源浪费
* 通过静态的Holder类持有真正的实例,间接实现了懒加载
*/
private static class SingletonHolder {
private static final Singleton1 singleton = new Singleton1();
private SingletonHolder() {
}
}
public synchronized static Singleton1 getInstance_4() {
return SingletonHolder.singleton;
}
}
单例模式学习
猜你喜欢
转载自blog.csdn.net/wuzhimin15181111/article/details/78626512
今日推荐
周排行