首页 > 代码库 > 单例模式----从零单排

单例模式----从零单排

单例模式: 保证一个类只有一个实例, 并提供一个全局访问点。(可以说是最简单的模式, 从零单排冲天梯)技术分享



类图:

技术分享


抽象实现:


1. 懒汉模式 (懒得判断是否已经实例化, 先进行实例化)

package com.wenniuwuren.singleton;

public class Singleton {
	
	// 懒汉模式
    /**
     * 私有且唯一的属性
     */
	private static Singleton uniqueInstance = new Singleton();
	
	/**
	 * 私有构造器保证不能被继承
	 */
	private Singleton() {
		
	}
	
	/**
	 * 全局访问点  static的修饰至关重要--提供给外部在不能实例化内部代码的时候通过类名访问内部public方法
	 */
	public static Singleton getInstance() {
		return uniqueInstance;
	}
	
	
	
}
适用于对程序性能有较大要求的地方, 如果用饱汉模式(详情见下文)要对线程加同步锁降低系统性能。



2. 饱汉模式(采用了volatile和同步块来保证并发安全性, 不像上面的懒汉模式直接就实例化了, 因为饱汉模式存在着判断和赋值,所以必须加上安全机制保障并发的正确性。 例如:线程A判断uniqueInstance为null进入方法, 然后new了实例, 但是还没赋值给uniqueInstance, 这时CPU把时间给了线程B, 此时的uniqueInstance还未赋值所以又new了一次实例, 那么这就破坏了单例模式了)

package com.wenniuwuren.singleton;

public class Singleton {

	
	// 饱汉模式
	/**
     * 私有且唯一的属性  
     * volatile修饰符保证变量仅存在于内存, 每个线程仅在内存中共享该变量, 从而保证了并发的安全性
     */
	private volatile static Singleton uniqueInstance = null;
	
	/**
	 * 私有构造器保证不能被继承
	 */
	private Singleton() {
		
	}
	
	/**
	 * 全局访问点
	 */
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			// 为空时才进行创建实例(延迟创建实例有助于节省不必要的资源占用)
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					return uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
	
}

当然如果系统对性能要求不高, 饱汉模式可以不像上面那么复杂, 直接在getInstance()方法上加同步修饰字段synchronized即可。



但是上面的方法虽然已经把同步代码块缩减到最小, 但是还是对性能有一点影响, 接下来介绍另一种保障线程安全的方法并且不使用同步代码块和volatile字段修饰。

public class Singleton {
    
    private Singleton(){}
    /**
     *    类级的内部类,只有被调用到时才会实例化
     */
    private static class SingletonHolder{
        private static Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}


应用场景:              

                - 网站的计数器, 不然并发计数访客什么的数量肯定会乱

                - 应用程序的日志, 并发写日志不控制安全性日志重复写入多次

                - Spring中的Bean默认也是单例的



参考书籍: 

                 《设计模式:可复用面向对象软件的基础》

                  《Java并发编程实战》




单例模式----从零单排