单例模式

来源:互联网 发布:剃刀数据 编辑:程序博客网 时间:2024/06/15 00:24
根据Head First 设计模式整理

单例模式简单实现:

Singleton.java

public class Singleton {    private static Singleton uniqueInstance;    private Singleton(){}    public static Singleton getInstance(){        if (uniqueInstance == null)            uniqueInstance = new Singleton();        return uniqueInstance;    }    public static void main(String[] args) {        Singleton ins1 = Singleton.getInstance();        Singleton ins2 = Singleton.getInstance();        System.out.println(ins1 == ins2);    }}

毫无疑问,打印的结果为true。

单例模式 : 确保一个类只有一个实例,并提供一个全局访问点( 私有的构造器, 静态方法, 静态变量)。

但上面的例子有一个问题,它不是线程安全的。

可以加上synchronized关键字

public class Singleton {    private static Singleton uniqueInstance;    private Singleton(){}    public static synchronized Singleton getInstance(){        if (uniqueInstance == null)            uniqueInstance = new Singleton();        return uniqueInstance;    }    public static void main(String[] args) {        Singleton ins1 = Singleton.getInstance();        Singleton ins2 = Singleton.getInstance();        System.out.println(ins1 == ins2);    }}

但这种做法也有问题,因为只有第一次执行方法时,才需要同步,这样会对性能造成额外的负担。

另一种做法是,在静态变量初始化时创建实例,jvm在加载这个类时马上创建唯一的实例,jvm保证在任何线程访问该静态变量之前,一定先创建此实例,所以这是这是线程安全的。

public class Singleton {    private static Singleton uniqueInstance = new Singleton();    private Singleton(){}    public static synchronized Singleton getInstance(){        if (uniqueInstance == null)            uniqueInstance = new Singleton();        return uniqueInstance;    }    public static void main(String[] args) {        Singleton ins1 = Singleton.getInstance();        Singleton ins2 = Singleton.getInstance();        System.out.println(ins1 == ins2);    }}

第三种方法是使用 double-checked locking ,先检查是否实例创建,未创建,则进行同步,这样就只同步一次。

public class Singleton {    private volatile static Singleton uniqueInstance ;    private Singleton(){}    public static synchronized Singleton getInstance(){        if (uniqueInstance == null) {          synchronized (Singleton.class){              if (uniqueInstance == null)                  uniqueInstance = new Singleton();          }            uniqueInstance = new Singleton();        }        return uniqueInstance;    }}

还要注意的是,如果使用多个类加载器,可能导致单例失效,而产生多个实例。

0 0
原创粉丝点击