创建型模式.单例模式-懒汉、饿汉、枚举、原子
2018-03-28 00:00
399 查看
1 安全发布对象的四种方法
在多线程中,为了保证线程安全性,我们要正确地发布对象,保证发布地对象不要逸出。在静态初始化函数中初始化一个对象引用
将对象的引用保存到volatile类型域或者AtomicReference对象中
将对象的引用保存到某个正确构造对象的final类型域中
将对象的引用保存到一个由锁保护的域中
2 懒汉单例模式
写法简单,适合简单、小的对象创建;当创建一个非常复杂、非常大I/O操作、非常耗内存的对象时,不宜采用;
package com.dhm.singleton; /** * 懒汉单例模式 * @author duhongming * @email 935720334@qq.com */ public class LazySingletonPattern { //方法1 声明为常量 private static final LazySingletonPattern instance = new LazySingletonPattern(); //方法2 静态代码块 /*private static LazySingletonPattern instance = null; static{ instance = new LazySingletonPattern(); }*/ //构造方法私有 private LazySingletonPattern(){} public static LazySingletonPattern getInstance() { return instance; } }
3 饿汉单例模式(volatile+双重检测机制)
适合绝大多数情况;编写复杂,由于加锁,对性能有一定影响;
package com.dhm.singleton; /** * 饿汉单例模式(volatile+双重检测机制) * @author duhongming * @email 935720334@qq.com * * 创建对象过程: * 1、memory = allocate()分配对象的内存空间 * 2、ctorInstance() 初始化对象 * 3、instance = memory 设置instance指向刚分配的内存 * * 2和3会发生指令重排 * * volatile作用:内存可见+防止指令重排 */ public class HungrySingletonPattern { /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */ private volatile static HungrySingletonPattern instance = null; /* 私有构造方法,防止被实例化 */ private HungrySingletonPattern(){} /* 因为我们只需要在创建类的时候进行同步,所以只要将创建和getInstance()分开,单独为创建加synchronized关键字 */ private static synchronized void syncInit() {//同步锁,静态方法锁定作用域是对象 if (instance == null) { instance = new HungrySingletonPattern(); } } /* 静态的工厂方法,创建实例 */ public static HungrySingletonPattern getInstance(){ if(instance == null){//双重检测机制 syncInit(); } return instance; } /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */ public Object readResolve(){ return instance; } }
4 枚举单例模式
终极解决方案,请使用!package com.dhm.singleton; /** * 枚举单例模式 * @author duhongming * @email 935720334@qq.com */ public class EnumSingletonPattern { private EnumSingletonPattern(){} public static EnumSingletonPattern getInstance() { return Singleton.INSTANCE.getIntance(); } private enum Singleton{ INSTANCE; private EnumSingletonPattern instance; //JVM保证这个只执行一次 Singleton(){ instance = new EnumSingletonPattern(); } public EnumSingletonPattern getIntance(){ return instance; } } }
5 原子布尔变量单例模式
呵呵,纯属娱乐!package com.dhm.singleton; import java.util.concurrent.atomic.AtomicBoolean; /** * 原子布尔变量单例模式 * @author duhongming * @email 935720334@qq.com */ public class AtomicBooleanSingletonPattern { private static final AtomicBoolean atomicBoolean = new AtomicBoolean(false); private AtomicBooleanSingletonPattern(){} private static AtomicBooleanSingletonPattern intance = null; public static AtomicBooleanSingletonPattern getInstance() { if(atomicBoolean.compareAndSet(false,true)){ intance = new AtomicBooleanSingletonPattern(); } return intance; } }
6 单例模式在多线程下的测试
package com.dhm.singleton; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; /** * 四种单例模式测试 * @author duhongming * @email 935720334@qq.com */ public class SingletonPatternTest{ private static final HungrySingletonPattern hungrySingletonPattern = HungrySingletonPattern.getInstance(); private static final LazySingletonPattern lazySingletonPattern = LazySingletonPattern.getInstance(); private static final EnumSingletonPattern enumSingletonPattern = EnumSingletonPattern.getInstance(); private static final AtomicBooleanSingletonPattern atomicBooleanSingletonPattern = AtomicBooleanSingletonPattern.getInstance(); /** * 初始化原子操作AtomicBoolean为false,只要有一个为false, * 它就会置为true,只要不为true,我们单例模式都是可以正常运行的 */ private static final AtomicBoolean atomicBoolean = new AtomicBoolean(false); private static final int TEST_NUM = 1000000; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); CountDownLatch countDownLatch1 = new CountDownLatch(TEST_NUM); CountDownLatch countDownLatch2 = new CountDownLatch(TEST_NUM); CountDownLatch countDownLatch3 = new CountDownLatch(TEST_NUM); CountDownLatch countDownLatch4 = new CountDownLatch(TEST_NUM); Long start1 = System.currentTimeMillis(); for (int i = 0; i < TEST_NUM; i++) { executorService.execute(()->{ try{ doHungrySingletonPatternTest(); } finally { countDownLatch1.countDown(); } }); } countDownLatch1.await(); System.out.println("doHungrySingletonPatternTest cost time:"+(System.currentTimeMillis()-start1)); Long start2 = System.currentTimeMillis(); for (int i = 0; i < TEST_NUM; i++) { executorService.execute(()->{ try{ doLazySingletonPatternTest(); } finally { countDownLatch2.countDown(); } }); } countDownLatch2.await(); System.out.println("doLazySingletonPatternTest cost time:"+(System.currentTimeMillis()-start2)); Long start3 = System.currentTimeMillis(); for (int i = 0; i < TEST_NUM; i++) { executorService.execute(()->{ try{ doEnumSingletonPatternTest(); } finally { countDownLatch3.countDown(); } }); } countDownLatch3.await(); System.out.println("doEnumSingletonPatternTest cost time:"+(System.currentTimeMillis()-start3)); Long start4 = System.currentTimeMillis(); for (int i = 0; i < TEST_NUM; i++) { executorService.execute(()->{ try{ doAtomicBooleanSingletonPatternTest(); } finally { countDownLatch4.countDown(); } }); } countDownLatch4.await(); System.out.println("doAtomicBooleanSingletonPatternTest cost time:"+(System.currentTimeMillis()-start4)); executorService.shutdown(); if(!atomicBoolean.get()){ System.out.println("单例模式测试通过!"); }else{ System.out.println("单例模式测试失败..."); } } private static void doHungrySingletonPatternTest(){ Boolean isEquals = hungrySingletonPattern.hashCode()==HungrySingletonPattern.getInstance().hashCode(); if(atomicBoolean.compareAndSet(isEquals,true)){ System.out.println("doHungrySingletonPatternTest fail"); } } private static void doLazySingletonPatternTest(){ Boolean isEquals = lazySingletonPattern.hashCode()==LazySingletonPattern.getInstance().hashCode(); if(atomicBoolean.compareAndSet(isEquals,true)){ System.out.println("doLazySingletonPatternTest fail"); } } private static void doEnumSingletonPatternTest(){ Boolean isEquals = enumSingletonPattern.hashCode()==EnumSingletonPattern.getInstance().hashCode(); if(atomicBoolean.compareAndSet(isEquals,true)){ System.out.println("doEnumSingletonPatternTest fail"); } } private static void doAtomicBooleanSingletonPatternTest(){ Boolean isEquals = atomicBooleanSingletonPattern.hashCode()==AtomicBooleanSingletonPattern.getInstance().hashCode(); if(atomicBoolean.compareAndSet(isEquals,true)){ System.out.println("doAtomicBooleanSingletonPatternTest fail"); } } }
相关文章推荐
- 单例模式五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式五种写法 懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举
- 单例模式的五种写法:饿汉,懒汉, 双重校验锁,静态内部类,枚举
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式的实现之懒汉,饿汉,双重校验锁,枚举和静态内部类以及单例模式的应用情景
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举。
- 设计模式之单例设计模式(饿汉单例设计模式&懒汉单例设计模式)
- 设计模式:单例模式,懒汉与饿汉
- 黑马程序员——单例设计模式,饿汉加懒汉
- 单例模式(懒汉模式、饿汉模式)
- C++实现一个单例模式(懒汉与饿汉)
- 单例设计模式(懒汉模式、饿汉模式)C++