简介
单例模式就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
举例
JDK里面的java.lang.Runtime 使用了单例模式(饿汉)
饿汉式(静态常量)
代码
//饿汉式(静态常量)
class SingleTone{
//私有化构造器方法,防止new方式创建对象
private SingleTone(){}
//静态成员变量存放对象,并初始化
private final static SingleTone singleton = new SingleTone();
//提供public静态方法,返回实例对象
public static SingleTone getInstance(){
return singleton;
}
}
讨论
优点:写法简单,在类装载的时候创建了对象,避免了线程同步问题。
缺点:在类装载的时候完成了实例化,没有达到Lazy Loading效果。如果从始至终都没有使用实例,则会 造成内存浪费。
结论:这种单例模式可用,但可能会照成内存浪费
饿汉式(静态代码块)
代码
//饿汉式(静态代码块)
class SingleTone{
//私有化构造器方法,防止new方式创建对象
private SingleTone(){}
//静态成员变量存放对象
private static SingleTone singleton;
static {
//静态代码块内部初始化实例
singleton = new SingleTone();
}
//提供public静态方法,返回实例对象
public static SingleTone getInstance(){
return singleton;
}
}
讨论
优点:写法简单,在类装载的时候创建了对象,避免了线程同步问题。
缺点:在类装载的时候完成了实例化,没有达到Lazy Loading效果。如果从始至终都没有使用实例,则会造成内存浪费。
结论:这种单例模式可用,但可能会照成内存浪费
懒汉式(线程不安全)
代码
//懒汉式(线程不安全)
class SingleTone{
//私有化构造器方法,防止new方式创建对象
private SingleTone(){}
//静态成员变量存放对象,并初始化
private static SingleTone singleton;
//提供public静态方法,判断实例对象是否为null,返回实例对象
public static SingleTone getInstance(){
if(singleton == null){
singleton = new SingleTone();
}
return singleton;
}
}
讨论
优点:起到Lazy Loading效果,但只能在单线程下使用。
缺点:如果在多线程下,一个线程进入了 if(singleton == null)判断语句,但未来得及向下执行,另一个线程也通过了判断语句,这时会产生多个对象。所以是线程不安全的。
结论:实际开发中不能使用这种方式。
懒汉式(线程安全,同步方法)
代码
//懒汉式(线程安全,同步方法)
class SingleTone{
//私有化构造器方法,防止new方式创建对象
private SingleTone(){}
//静态成员变量存放对象,并初始化
private static SingleTone singleton;
//提供public静态方法,判断实例对象是否为null,返回实例对象。添加同步机制实现线程安全
public static synchronized SingleTone getInstance(){
if(singleton == null){
singleton = new SingleTone();
}
return singleton;
}
}
讨论
优点:起到Lazy Loading效果,保证了线程安全。
缺点:效率太低,每个线程想要获取实例的时候都要排队,而实际上这个方法只执行一次代码实例化就够了。
结论:实际开发中不推荐使用这种方式。
懒汉式(双重检查)
代码
//懒汉式(双重检查)
class SingleTone{
//私有化构造器方法,防止new方式创建对象
private SingleTone(){}
//静态成员变量存放对象
private static volatile SingleTone singleton;
//提供public静态方法,判断实例对象是否为null,返回实例对象。添加同步机制实现线程安全。
public static SingleTone getInstance(){
if(singleton == null){
synchronized (SingleTone.class){
if(singleton == null){
singleton = new SingleTone();
}
}
}
return singleton;
}
}
讨论
优点:起到Lazy Loading效果,保证了线程安全,效率较高 。
结论:实际开发中推荐使用这种方式。
静态内部类
代码
//静态内部类
class SingleTone{
//私有化构造器方法,防止new方式创建对象
private SingleTone(){}
//利用静态内部类在外部类加载的时候并不加载的特点保证了懒加载,同时利用内部类加载的时候进行实例化来保证了线程安全
private static class SingletonInstance{
private static final SingleTone INSTANCE = new SingleTone();
}
//提供public静态方法,判断实例对象是否为null,返回实例对象。
public static SingleTone getInstance(){
return SingletonInstance.INSTANCE;
}
}
讨论
优点:起到Lazy Loading效果,保证了线程安全,效率较高 。
结论:实际开发中推荐使用这种方式。
枚举
代码
//枚举
enum SingleTone{
INSTANCE;
public void method(){
}
}
讨论
优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建对象 。
结论:实际开发中推荐使用这种方式。