标签:exception 同步 row size 区域 初始 except 屏蔽 结果
一:饿汉式单例模式,优点:线程绝对安全,无锁,效率高。缺点:类加载的时候就初始化,不管用不用,都占用空间。
public class HungrySingleton { //先静态、后动态 //先属性、后方法 //先上后下 private static final HungrySingleton hungrySingleton = new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){ return hungrySingleton; } }
二:懒汉式单例
①简单懒汉式单例,优点:在外部需要使用的时候才进行实例化 缺点:线程不安全
public class LazySimpleSingleton { private LazySimpleSingleton(){} //静态块,公共内存区域 //不能加final,final修饰变量必须直接赋值,或者在静态块赋值。否则报错 private static LazySimpleSingleton lazy = null; public synchronized static LazySimpleSingleton getInstance(){ if(lazy == null){ lazy = new LazySimpleSingleton(); } return lazy; } }
②双重检查懒汉式单例,
public class LazyDoubleCheckSingleton { //volatile 关键字禁止指令重排序,保证线程安全 private volatile static LazyDoubleCheckSingleton lazy = null; private LazyDoubleCheckSingleton(){} public static LazyDoubleCheckSingleton getInstance(){ //第一次检查,减少竞争锁 if(lazy == null){ synchronized (LazyDoubleCheckSingleton.class){ //第二次检查,因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话就会生成多个实例 if(lazy == null){ lazy = new LazyDoubleCheckSingleton(); //1.分配内存给这个对象 //2.初始化对象 //3.设置lazy指向刚分配的内存地址 //4.初次访问对象 //因为jvm指令可能会重排序导致2,3可能会赋值错误,所以需要对象加上volatile 关键字 } } } return lazy; } }
③内部类实现单例 优点://完美地屏蔽了饿汉式的内存浪费,和synchronized性能问题 ,史上最牛B的单例模式的实现方式
public class LazyInnerClassSingleton {
//默认使用LazyInnerClassGeneral的时候,会先初始化内部类 //如果没使用的话,内部类是不加载的 private LazyInnerClassSingleton(){ if(LazyHolder.LAZY != null){ throw new RuntimeException("不允许创建多个实例"); } } //每一个关键字都不是多余的 //static 是为了使单例的空间共享 //保证这个方法不会被重写,重载 public static final LazyInnerClassSingleton getInstance(){ //在返回结果以前,一定会先加载内部类 return LazyHolder.LAZY; } //默认不加载 private static class LazyHolder{ private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton(); } }
标签:exception 同步 row size 区域 初始 except 屏蔽 结果
原文地址:https://www.cnblogs.com/betterOne/p/12160661.html