1、普通单例模式
此类缺陷:无法应对多线程问题
package com.boonya.pattern.singleton;
/**
* 单例示例
* <li>文件名称: Singleton</li>
* <li>文件描述: $单例示例类</li>
* <li>内容摘要: 单例的创建</li>
* <li>完成日期:2013-9-27</li>
* <li>示例编写: BOONYACHENGDU@GMAIL.COM</li>
* <li>应用场景:频繁使用的对象且值不变,一如组件之类的对象</li>
*/
public class Singleton
{
/**
* 无论是否调用都会实例化
*/
private static Singleton singleton=new Singleton();
/**
* 确保外部不能实例化,即使用new关键字无效
*/
private Singleton(){
System.out.println("singleton constructor");
}
/**
* 必须确保同步,否则多线程情况下值不统一 但 synchronized 关键字使用会降低系统性能
*/
public static /*synchronized*/ Singleton getInstance(){
return singleton;
}
}
2、懒加载单例模式
此类缺陷:使用多线程时系统性能明显下降
package com.boonya.pattern.singleton;
/**
* 单例示例
* <li>文件名称: LazySingleton</li>
* <li>文件描述: $单例示例类</li>
* <li>内容摘要: 单例的创建</li>
* <li>完成日期:2013-9-27</li>
* <li>示例编写: BOONYACHENGDU@GMAIL.COM</li>
* <li>应用场景:频繁使用的对象且值不变,一如组件之类的对象</li>
*/
public class LazySingleton
{
/**
* 调用的时候再实例化
*/
private static LazySingleton singleton=null;
/**
* 确保外部不能实例化,即使用new关键字无效
*/
private LazySingleton(){
System.out.println("singleton constructor");
}
/**
* 必须确保同步,否则多线程情况下值不统一(线程执行先后可能判断为null)
*/
public static synchronized LazySingleton getInstance(){
if(singleton==null){
singleton=new LazySingleton();
}
return singleton;
}
}
3、加强(plus)单例
此类缺陷:使用反射机制时,会强行调用单例类的私有构造器,生成多个实例
package com.boonya.pattern.singleton;
/**
* 单例示例
* <li>文件名称: PlusSingleton</li>
* <li>文件描述: $单例示例类</li>
* <li>内容摘要: 单例的创建</li>
* <li>完成日期:2013-9-27</li>
* <li>示例编写: BOONYACHENGDU@GMAIL.COM</li>
* <li>应用场景:频繁使用的对象且值不变,一如组件之类的对象</li>
*/
public class PlusSingleton
{
/**
* 确保外部不能实例化,即使用new关键字无效
*/
private PlusSingleton(){
System.out.println("singleton constructor");
}
/**
* 内部类JVM初始换调用
*/
private static class SingletonObject{
private static PlusSingleton singleton=new PlusSingleton();
}
/**
* 不需要考虑多线程问题
*/
public static PlusSingleton getInstance(){
return SingletonObject.singleton;
}
}
4、序列化单例
此类缺陷:序列化和反序列化都有可能会破坏单例
package com.boonya.pattern.singleton;
import java.io.Serializable;
/**
* 单例示例
* <li>文件名称: Singleton</li>
* <li>文件描述: $单例示例类</li>
* <li>内容摘要: 单例的创建</li>
* <li>完成日期:2013-9-27</li>
* <li>示例编写: BOONYACHENGDU@GMAIL.COM</li>
* <li>应用场景:频繁使用的对象且值不变,一如组件之类的对象 序列化操作需慎重</li>
*/
@SuppressWarnings("serial")
public class SerializableSingleton implements Serializable
{
private String context;
public String getContext()
{
return context;
}
public void setContext(String context)
{
this.context = context;
}
/**
* 无论是否调用都会实例化
*/
private static SerializableSingleton instance=new SerializableSingleton();
/**
* 确保外部不能实例化,即使用new关键字无效
*/
private SerializableSingleton(){
System.out.println("singleton constructor");
context="SerializableSingleton";
}
/**
* 获取单例对象
*/
public static SerializableSingleton getInstance(){
return instance;
}
/**
* 阻止生成新的实例,总是返回当前对象(此方法不可去掉否则序列化和反序列化会出错)
*/
private Object readResolve(){
return instance;
}
}
5、性能和注意事项
(1)、频繁使用的对象且值不变,一如组件之类的对象建议使用单例。此处建议使用懒加载方式,使用的时候再实例化,降低JVM初始化static 时new实例化对象消耗性能,减少GC机制的执行。
(2)、考虑是否会在多线程中使用到,多线程中使用单例消耗性能严重。
(3)、使用单例时,尽量不要使用序列化操作,危险难以预测,最好是具体问题具体分析。