单例设计模式
单例设计模式有好几种,包括懒汉式单例、饿汉式单例、登记式单例(暂不介绍)。
单例设计的特点是:(1)单例类只能有一个实例。(2)单例类必须自己创建自己的唯一实例。(3)单例类必须给所有的其他对象提供这一实例。
1、懒汉式单例
最基本的例子:
public class Singleton{
private Singleton(){}
private Singleton single = null;
public static Singleton getInstance(){
if(single == null){
single = new Singleton();
}
return single;
}
}
public class SingletonDemo{
public static void main(String[]args){
Singleton s1 = null;
Singleton s2 = null;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
}
}
Singleton的构造方法限定为private,避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。以上实现没有考虑到线程 安全的问题,它是线程不安全的。必须通过改造getInstance()方法确保线程安全。
(1) 在getInstance()方法上加同步
public static synchronized Singleton getInstance(){
if(single == null){
single = new Singleton();
}
return single;
}
(2) 双重检查锁定
public static Singleton getInstance(){
if(single == null){
synchronized(Singleton.class){
if(single == null){
single = new Singleton();
}
}
}
return single;
}
(3) 静态内部类
public class Singleton{
private static class LazyHolder{
private static final Singleton INSTANCE = new Singleton();
private Singleton(){}
public static final Singleton getInstance(){
return LazyHolder.INSTANCE;
}
}
}
2、饿汉式单例
java代码
class Singleton{
private Singleton(){}
private Singleton single = new Singleton();
public static Singleton getInstance(){
return single;
}
public void print(){
System.out.println("Hello,world");
}
}
public class SingletonDemo{
public static void main(String[]args){
Singleton s1 = null;
Singleton s2 = null;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
s1.print();
s2.print();
}
}
饿汉式就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,而懒汉式比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
在线程安全方面,饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,懒汉式本身是非线程安全的,为了实现线程安全有以上几种写法。在资源加载和性能方面,饿汉式在类创建的同时就实例化一个静态对象,不管会不会使用这个单例,都会占据内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,而懒汉式,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟。懒汉式创建好实例之后就和饿汉式一样了。由于在getInstance()方法上加同步,双重检查锁定,静态内部类都实现了线程安全,但是前两种方法影响性能,静态内部类在这里面是性能最佳的。