1.单例模式
一 最简单的实现方法
定义一个私有的构造函数,保证对象不能为外部实例化,同时返回一个静态对象实例。
public class SinglertonClass{
public static final SingletonClass getInstance = new SingletonClass();
private SinglertonClass(){
}
}
上述方法缺点是无论这个对象是否被使用,都会默认创建一个对象,如果对象很重造成资源浪费。
二 lazy—loaded(延时加载,需要用的时候才去初始化)
public class SingletonClass{
private static SingletonClass instance = null;
public static SingletonClass getInstance(){
if(instance == null){
instance = new SingletonClass();
}
return instance;
}
private SingletonClass(){
}
}
这段代码在单线程的时候有效,但在多线程场景下,并不能保证只有一个实例。
当多个线程同时发现对象为null时,都会各自去new一个对象。
三 加锁(double-checked locking)
public class SingletonClass{
private static SingletonClass instance = null;
public static SingletonClass getInstance(){
if(instance == null){
synchronized(SingletonClass.class){
if(instance == null){
instance = new SingletonClass();
}
}
}
return instance;
}
private SingletonClass(){
}
四 静态内部类
public class SingletonClass {
private static class SingletonClassInstance{
private static final SingletonClass instance = new SingletonClass();
}
public static SingletonClass getInstance(){
return SingletonClassInstance.instance;
}
private SingletonClass(){
}
}
上述单例模式实现代码中,使用了Java的静态内部类。在这段代码中,因为SingletonClass没有static的属性,因此并不会被初始化。直到调用getInstance()的时候,会首先加载SingletonClassInstance类,这个类有一个static的SingletonClass实例,因此需要调用SingletonClass的构造方法,然后getInstance()将把这个内部类的instance返回给使用者。由于这个instance是static的,因此并不会构造多次。
由于SingletonClassInstance是私有静态内部类,所以不会被其他类知道,同样,static语义也要求不会有多个实例存在。并且,JSL规范定义,类的构造必须是原子性的,非并发的,因此不需要加同步块。同样,由于这个构造是并发的,所以getInstance()也并不需要加同步。并且Effiective Java也推荐的这种方式。
注意:懒汉模式在运行的时候获取对象比较慢(因为类加载是并没有创建对象实例),但是加载类的时候比较快(因为此时不创建对象实例),饿汉模式是在运行的时候获取对象较快(因为在加载类是就创建了对象实例),加载类的时候慢(此时还需要创建对象实例)。

浙公网安备 33010602011771号