标签:loading 简单 pen 构造 执行 public 私有化 不同 二次
单例模式(Singleton Pattern) :确保一个类只有一个实例,并提供一个全局访问点。
应用场景:
单例模式的特点:
单元素的枚举类是实现单例模式的最佳方式 出自《effective java》
常用的单例模式:
public class Singlenton{
private final static Singleton uniqueInstance = new Singleton();
private Singlenton(){
}
public static Singleton getUniqueInstance(){
return uniqueInstance;
}
}
public class Singlenton{
private final static Singleton uniqueInstance;
static{
uniqueInstance = new Singleton();
}
private Singlenton(){
}
public static Singleton getUniqueInstance(){
return uniqueInstance;
}
}
饿汉式,线程安全,利用类加载机制,静态变量和静态代码块,在类加载时就会执行,并且只执行一次,避免了多线程问题,但是丢失了延迟实例化带来的节约资源的好处。
public class Singleton{
private static Singleton uniqueInstance;
private Singleton(){
}
public static Singleton getInstance(){
if(uniqueInstance==null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
synchronized
关键字,但是效率会大大降低,因为不管实例有无创建,线程只有调用了getInstance方法想用获取实例,都会被阻塞,等待资源。public class Singleton{
private volatile static Singleton uniqueInstance;
private Singleton(){
}
public static Singleton getInstance(){
if(uniqueInstance==null){
synchronized(Singleton.class){
if(uniqueInstance==null){
uniqueInstace = new Singleton();
}
}
}
return uniqueInstance;
}
}
双重校验锁的好处:
第一个if判断,保证了调用实例的线程都能进入方法,当实例已经创建时,可以直接返回实例对象,不需要等待。第二个if判断,是为了防止当两个线程同时进入第一个if判断里面,当线程一拿到锁,创建实例后,释放锁,线程二得到锁,因为有第二层的if判断实例是否创建,就能避免进行第二次实例化。
volatile关键字:
禁止JVM指令重排,保证在多线程环境下也能正常运行。
由于JVM具有指令重排的特性。实例在创建时需要三个步骤执行:1、为实例分配内存空间,2、初始化实例(实例可以不能null,需要初始化清理),3、将实例指向分配好的内存空间。当在单线程下,无影响,但是多线程时,当线程一执行了1和3,线程二调用getInstance方法,发现实例uniqueInstace不为null,就会把未初始化的实例返回。
什么是线程安全问题:
当多线程时,有可能出现同时访问同一个资源的情况,由于每个线程执行过程不可控,所以很可能导致最终结果与实际上期望的结果不同,或者直接导致程序出错。
线程安全:概括起来,保证可见性。
public class Singleton{
private Singleton(){
}
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
当Singleton类加载时,静态内部类还没有加载,只有当调用了getInstance方法,才会调用SingletonHolder,并且只会调用一次实例化。之后调用getInstance方法,就直接返回之前的实例对象,保证单例。
public enum EnumSingleton{
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
完整枚举单例:
public class User{
//私有化构造器
private User(){
}
//定义静态枚举类
static enum SingletonEnum{
//创建一个枚举对象,该对象天生为单例
INSTANCE;
private User user;
//私有化构造器
private SingletonEnum(){
User user = new User();
}
public User getInstance(){
return user;
}
}
//对外暴露一个获取User对象的静态方法
public static User getUser(){
return SingletonEnum.INSTANCE.getInstance();
}
}
枚举实现的优点:
标签:loading 简单 pen 构造 执行 public 私有化 不同 二次
原文地址:https://www.cnblogs.com/jayzou/p/14389310.html