为什么要用单例模式
当一个类需要用来管理共享资源的时候,我们就只需要一个对象,比方说:线程池、缓存、日志对象等。如果说制造出了多个实例,就会导致许多问题的产生,例如:程序异常,资源使用过量,结果不一致等。
Java实现单例思想
- 私有构造函数 → 其他类不能实例化一个新的对象。
- 私有化引用 → 不能进行外部修改。
- 公有静态方法是唯一可以获得对象的方式。
实现方法
经典实现方法
package com.singleton;
/**
* 懒汉写法 缺点:没有达到lazy loading的效果
* 金典单例实现只适用于单线程的情况,当有多个线程并发时,
* 它们都要执行这段代码,都执行到第6行,这时 sl都为空,于是乎就会实例出多个对象了,这就违背了单例模式的思想了。
* * @author yonney
*/
public class LazySingleton {
private static LazySingleton singleton;
private LazySingleton(){
}
public static LazySingleton getInstance(){
if( singleton== null){
singleton = new LazySingleton();
}
return singleton;
}
}
getInstance()方法上加上synchronized关键字
public class Singleton {
private static Singleton sl;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if(sl == null) {
sl = new Singleton();
}
return sl;
}
//其他的方法
}
注意:但是我们可以想象得到,真正需要同步的是在第一次调用时,之后就不再需要同步这个方法了。之后的每次调用,同步都会是一种累赘。程序执行的效率就会大大降低。
恶汉写法(JVM虚拟机在加载这个类时就会立马创建此唯一的单例。)
public class HungrySingleton {
private static HungrySingleton singleton = new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return singleton;
}
}
ThreadLocal实现
/**
* 使用ThreadLocal实现线程范围内的共享
*/
public class ThreadLocalSingleton {
private static ThreadLocal<ThreadLocalSingleton> map = new ThreadLocal<ThreadLocalSingleton>();
public static ThreadLocalSingleton getThreadInstance() {
ThreadLocalSingleton instance = map.get();
if (instance == null) {
instance = new ThreadLocalSingleton();
map.set(instance);
}
return instance;
}
}
双重校验锁,在当前的内存模型中无效
public class LockSingleton {
private volatile static LockSingleton singleton;
private LockSingleton(){
}
public static LockSingleton getInstance(){
if( singleton == null){
synchronized (LockSingleton. class) {
if( singleton == null){
singleton = new LockSingleton();
}
}
}
return singleton;
}
}
内部静态方法
/**
* 内部静态方法 优点:加载时不会初始化静态变量INSTANCE,因为没有主动使用,达到Lazy loading
* @author yonney
*
*/
public class InternalSingleton {
private static class SingletonHolder{
private final static InternalSingleton INSTANCE = new InternalSingleton();
}
private InternalSingleton(){
}
public static InternalSingleton getInstance(){
return SingletonHolder. INSTANCE;
}
}
枚举实现
/**
* 枚举,《Effective Java》作者推荐使用的方法,优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
* @author yonney
*/
public enum EnumSingleton {
INSTANCE;
public static EnumSingleton getInstance(){
return INSTANCE ;
}
public Object o;
public Object testObject(){
if( o== null){
return new Object();
}
return o;
}
public static void main(String args[]){
if(EnumSingleton. getInstance().testObject()==EnumSingleton. getInstance().testObject()){
}
}
}