• 单例设计模式singleton


    简单引入

    单例设计模式作为最简单,最常用的设计模式。一般是这两中写法,这两种写法教科书所谓的标准写法,但是实际上存在不少问题。后面介绍标准写法,以规避这些问题。

    1.懒汉式:

    
    /**
    	 * 问题在于,当多线程工作的时候,如果有多个线程同时运行到if (instance ==
    	 * null),都判断为null,那么两个线程就各自会创建一个实例——这样一来,就不是单例了。
    	 */
    class Singleton {
    
    	private Singleton() {
    	};
    
    	private static Singleton s;
    
    	public static Singleton getInstance() {
    		if (s == null) {
    			s = new Singleton();
    		}
    		return s;
    	}
    
    }
    
    

    2.恶汉式

    class Singleton {
    	private Singleton() {
    	}
    
    	private static Singleton singleton = new Singleton();
    
    	public static Singleton getInstance() {
    		return singleton;
    	}
    
    }
    

    标准写法

    改变懒汉式1.

    (规避线程安全问题)加上 synchronized修饰方法即可

    class Singleton {
    
    	private Singleton() {
    	};
    
    	private static Singleton s;
    
    	public static synchronized Singleton getInstance() {
    		if (s == null) {
    			s = new Singleton();
    		}
    		return s;
    	}
    
    }
    
    

    改变懒汉式2. 双重检查 Double-Check』写法

    1.第一个if 只有instance为null的时候,才进入synchronized的代码段——大大减少了几率。
    2.第二个if 是为了防止可能出现多个实例的情况。

     class DoubleCheck {
    
    	private DoubleCheck() {
    	}
    
    	private static DoubleCheck dCheck;
    
    	public static DoubleCheck getInstance() {
    		if (dCheck == null) {
    			synchronized (DoubleCheck.class) {
    				if (dCheck == null) {
    					dCheck = new DoubleCheck();
    				}
    			}
    		}
    		return dCheck;
    	}
    
    }
    
    

    改变懒汉式2.之终极版 防止指令重排列 volatile

    不知道原子操作,与指令重排的建议复习下

     class DoubleCheck2 {
    	private DoubleCheck2() {
    	}
    
    	private static volatile DoubleCheck2 sCheck;
    
    	public static DoubleCheck2 getInstance() {
    		if (sCheck == null) {
    			synchronized (DoubleCheck2.class) {
    				if (sCheck == null) {
    					sCheck = new DoubleCheck2();
    				}
    			}
    		}
    		return sCheck;
    	}
    
    }
    
    

    1.恶汉式:

    说白了,有classloder装载 就是一开始就创建类

    /*
    	 * 缺点也就只是饿汉式单例本身的缺点所在了——由于INSTANCE的初始化是在类加载时进行的,而类的加载是由ClassLoader来做的,
    	 * 所以开发者本来对于它初始化的时机就很难去准确把握:
    	 * 
    	 * 可能由于初始化的太早,造成资源的浪费 如果初始化本身依赖于一些其他数据,那么也就很难保证其他数据会在它初始化之前准备好。
    	 */
    class Singleton {
    	private Singleton() {
    	}
    
    	private static final Singleton singleton = new Singleton();
    
    	public static Singleton getInstance() {
    		return singleton;
    	}
    
    }
    
    

    由于静态内部类实现

    class innerSingleton {
    	private innerSingleton() {
    
    	}
    
    	private static class SingletonHolder {
    		private static final innerSingleton SINGLETON = new innerSingleton();
    	}
    
    	public static innerSingleton getInstance() {
    		return SingletonHolder.SINGLETON;
    	}
    
    }
    
  • 相关阅读:
    LINQ中selectManay操作符(五)
    LINQ中select操作符(四)
    高效并发进阶-白银
    JVM回收算法
    一个类是怎么被JVM执行的
    一纸理解JVM
    单例模式
    深入理解Spring AOP思想
    深入理解Spring IOC工作原理
    HashMap扩容全过程
  • 原文地址:https://www.cnblogs.com/dgwblog/p/9114189.html
Copyright © 2020-2023  润新知