单例模式
/*
* 饿汉模式
*
* 静态常量方式实现
* 优点:在类加载的时候就完成实例化,避免了线程同步问题。
* 缺点:如果从未使用过这个对象,会造成内存的浪费。
* */
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 版权协议,转载请附上原文出处链接和本声明。