定义:确保一个类只有一个实例,并提供一个全局访问点。
要点:
- 单件模式确保程序中一个类最多只有一个实例。
- 单件模式也提供访问这个实例的全局点。
- 在java中实现单件模式需要私有的构造器、一个静态方法和一个静态变量。
- 确定在性能和资源上的限制,然后小心地选择适当的方案来实现单件,以解决多线程的问题(我们必须认定所有的程序都是多线程的)。
- JDK1.4版本及之前,双重检查加锁实现会失效。
- 如果使用多个类加载器,可能导致单件失效而产生多个实例。每个类加载器定义了一个命名空间,如果有两个以上,不同的类加载器可能会加载同一个类,从而产生多个单件并存的怪异现象。
- 如果使用jvm1.2或之前的版本,你必须建立单件注册表,以免垃圾收集器将单件回收。
- 通俗讲的饿汉式和懒汉式,指的就是单件的急切实例化和延迟实例化。
- 全局变量比单件模式差,全局变量可能造成命名空间的污染,不能确保只有一个实例。
单件实现方式一:非线程安全
package com.example.pattern.singleton;
/**
* <p>
* <code>Singleton</code>
* </p>
* Description: 线程不安全,在多线程环境下可能创建多个实例
*
* @author Mcchu
* @date 2018/1/17 14:27
*/
public class Singleton {
/**
* 单件变量
*/
private static Singleton uniqueInstance;
/**
* 声明私有构造器
*/
private Singleton(){ }
/**
* 外部调用方法
* @return uniqueInstance
*/
public static Singleton getInstance(){
if ( uniqueInstance==null ){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
package com.example.pattern.singleton;
/**
* <p>
* <code>SingletonThreadSafeRepeat</code>
* </p>
* Description: 线程安全,但是降低了性能,因为只有第一次创建单件时才需要做线程控制
*
* @author Mcchu
* @date 2018/1/17 15:13
*/
public class SingletonThreadSafeRepeat {
/**
* 单件变量
*/
private static SingletonThreadSafeRepeat uniqueInstance;
/**
* 私有构造器
*/
private SingletonThreadSafeRepeat(){};
/**
* 对外公开
* @return uniqueInstance
*/
public static synchronized SingletonThreadSafeRepeat getInstance(){
if ( uniqueInstance==null ){
uniqueInstance = new SingletonThreadSafeRepeat();
}
return uniqueInstance;
}
}
单件模式实现方式三:饿汉式-急切创建
package com.example.pattern.singleton;
/**
* <p>
* <code>SingletonThreadSafe</code>
* </p>
* Description: 线程安全->依赖jvm在加载这个类时马上创建此唯一的单件实例
*
* @author Mcchu
* @date 2018/1/17 14:47
*/
public class SingletonThreadSafe {
/**
* “急切”创建实例(又称饿汉式),
*/
private static SingletonThreadSafe uniqueInstance = new SingletonThreadSafe();
/**
* 声明私有构造器
*/
private SingletonThreadSafe(){}
/**
* 直接使用上面创建的实例
* @return uniqueInstance
*/
public static SingletonThreadSafe getInstance(){
return uniqueInstance;
}
}
单件模式实现方式四:双重检查加锁
package com.example.pattern.singleton;
/**
* <p>
* <code>SingletonDoubleLockThreadSafe</code>
* </p>
* Description: 双重加锁->double-checked locking,线程安全
*
* @author Mcchu
* @date 2018/1/17 14:49
*/
public class SingletonDoubleLockThreadSafe {
/**
* JDK1.4及更早版本,JCM对于volatile关键字的实现会导致双重检查加锁失效,所以不要用此方法实现
*/
private volatile static SingletonDoubleLockThreadSafe uniqueInstance;
/**
* 私有构造器
*/
private SingletonDoubleLockThreadSafe(){};
public static SingletonDoubleLockThreadSafe getInstance(){
if ( uniqueInstance==null ){
// 注意,这里是在不存在时进入同步区块
synchronized ( SingletonDoubleLockThreadSafe.class ){
if ( uniqueInstance==null ){
uniqueInstance = new SingletonDoubleLockThreadSafe();
}
}
}
return uniqueInstance;
}
}
附:
Head First设计模式第五章