单例模式、多例模式

  • Post author:
  • Post category:其他

单例模式

/*
* 饿汉模式
*
* 静态常量方式实现
* 优点:在类加载的时候就完成实例化,避免了线程同步问题。
* 缺点:如果从未使用过这个对象,会造成内存的浪费。
* */
public class Singleton {
	// 私有化构造器,不让外界实例化对象
	private Singleton() {}
	private static final Singleton singleton = new Singleton();
	public static Singleton getInstance() {
		return singleton;
	}
}
/*
* 懒汉模式
* 第一种实现方式
* 
* 步骤 1.1
* 方法上添加 synchronized 
* 
* 可以实现线程安全,但效率低,每次都会竞争同步锁,然后才在同步代码块中进行非空验证。
* 
* 我们的最终目的是只创建一个实例,创建了实例后 singleton 非空就会直接返回对象引用,
* 而不用每次进行锁竞争后在同步代码块中进行非空验证。
* */
public class Singleton {
	private Singleton() {}
	private static Singleton singleton = null;
	public static synchronized Singleton getInstance() {
		if (singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
}
/*
* 步骤 1.2
* 双重非空检查
* 
* 该种方式有Bug
* Bug是由Java的无序写入造成的,一般来讲,当初始化一个对象的时候,会经历
* a. 内存分配
* b. 初始化
* c. 返回对象引用
* 但是Java的无序写入可能会造成顺序的颠倒,即
* a. 内存分配
* b. 返回对象引用
* c. 初始化
* 这种情况下,singleton 已经不是null,而是指向了堆上的一个对象,但是该对象却还没有完成初始化动作,
* 当后续的线程发现 singleton 不是null而直接使用的时候,就会出现意料之外的问题。
* 
* 解决方案:JDK1.5之后,可以使用 volatile 关键字修饰变量来解决无序写入产生的问题,因为 volatile 关键字的一个重要作用是
* 禁止指令重排序,即保证不会出现内存分配、返回对象引用、初始化这样的顺序,从而使得双重检测真正发挥作用。
* */
public class Singleton {
	private Singleton() {}
	private static Singleton singleton = null;
	public static Singleton getInstance() {
		if (singleton == null) {
			synchronized (Singleton.class) {
				if (singleton == null) {
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}
/*
* 步骤 1.3
* 最终方案
* 
* 线程安全、延迟加载、效率较高
* */
public class Singleton {
	private Singleton() {}
	private volatile static Singleton singleton = null;
	public static Singleton getInstance() {
		if (singleton == null) {
			synchronized (Singleton.class) {
				if (singleton == null) {
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}
/*
* 懒汉模式
* 第二种实现方式
* 
* 静态内部类方式
* 原理:类的静态属性只会在第一次加载类的时候初始化,类的加载机制保证初始化实例时只有一个线程。
* 
* 静态内部类在 Singleton 类被加载时并不会立即实例化,而是在需要实例化时,
* 调用 getInstance 方法,才会加载 SingletonClass 类,从而完成 singleton 的实例化。
* 
* 线程安全、延迟加载、效率高
* */
public class Singleton {
	private Singleton(){}
	private static class SingletonClass {
		private static final Singleton singleton = new Singleton();
	}
	public static Singleton getInstance() {
		return SingletonClass.singleton;
	}
}

多例模式

/**
 * @Desc 多例模式,懒汉模式,用到才创建对象,资源最优
 */
public class Multition {
	
	private static final int COUNT = 2;
	
	private static final Random RANDOM = new Random();

	private Multition() {}
	
	private static final class MultitionInstance {
		private static final List<Multition> MultitionList = new ArrayList<Multition>(COUNT);
		static {
			for (int i = 0; i < COUNT; i++) {
				MultitionList.add(new Multition());
			}
		}
	}
	
	public static Multition getInstanceList() {
		return MultitionInstance.MultitionList.get(RANDOM.nextInt(COUNT));
	}
}

版权声明:本文为lercent原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。