单例模式确保一个类只有一个实例,并提供一个全局访问点。
Java中实现单例模式,需要
一个私有的构造器
一个静态方法
一个静态变量
1.简单的单例模式:
public class Singleton{
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = Singleton.getInstance();
}
return uniqueInstance;
}
}
此例虽然能够实现单例,但是是单线程模式,在多线程情况下,还是会出现多线程灾难。
2.在多线程情况下使用单例模式,需要把getInstance()改写成同步(synchronized)方法(使用synchronized关键字,迫使每个线程在进入方法之前,要等候别的线程释放该方法,不会有两个线程使用该方法。)
public class Singleton{
private static Singleton uniqueInstance;
private Singleton() {}
public static synchronized Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = Singleton.getInstance();
}
return uniqueInstance;
}
}
加入关键字synchronized虽然能够实现同步,但却降低了性能。
3.优化多线程
(1)getInstance()的性能
如果你的程序可以接受getInstance()造成的额外负担,则可以忽略此事;但是如果getInstance()的程序使用在频繁的地方,就得重新考虑额。
(2)eagerly创建单例,而不是延迟实例化
public class Singleton{
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
private static Singleton getInstance(){
return uniqueInstance;
}
}
在静态初始化器中创建单例,保证了线程安全。依赖JVM在加载类时创建此唯一的单例实例,JVM保证了在任何线程访问uniqueInstance变量开始之前,一定先创建此实例。
(3)使用“双重检查加锁”,在getInstance()中减少使用同步
首先检查实例是否已经创建了,如果为创建,才进行同步。
使用volatile关键字:确保当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地处理uniqueInstance变量。
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null){
//只有第一次才彻底执行此处代码
synchronized (Singleton.class) {
if(uniqueInstance == null){
//进入块内,仍为null,才创建
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
volatile需要在jdk1.5(含)以上版本中使用。