在 Java 应用中,单例对象就是保证在一个 JVM 中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了 new 操作符,降低了系统内存的使用频率,减轻 GC 压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。
单例模式有三步:
1.持有私有静态实例,防止被引用
2.私有构造方法,防止被实例化
3.对外提供方法获取实例。
记住这三步,来完成单例模式.
常用的单例模式有两种,懒汉式和饿汉式,先介绍懒汉式:
/**
* (懒汉式)
*/
public class Singleton {
/**
* 第一步 持有私有静态实例,防止被引用,
* 此处赋值为 null,目的是实现延迟加载
*/
private static Singleton instance = null;
/**
* 第二步 Constructor:私有构造方法,防止被实例化
*/
private Singleton() {
}
/**
* 第三步 静态工程方法,创建实例
*/
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这个类可以满足基本要求,但是,像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,
肯定就会出现问题了,如何解决?我们首先会想到对 getInstance 方法加 synchronized 关键字,
我们修改第三步,加上synchronized,如下:
/**
* 第三步 静态工程方法,创建实例
*/
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
但是,synchronized 关键字锁住的是这个对象,这样的用法,在性能上会有所下降,因为每次调用
getInstance(),都要对对象上锁,事实上,只有在第一次创建对象的时候需要加锁,之后就不需要了,
所以,这个地方需要改进。我们改成下面这个:
/**
* 第三步 静态工程方法,创建实例
*/
public static Singleton getInstance() {
if (instance == null ) {
synchronized (instance) {
if (instance == null ) {
instance = new Singleton();
}
}
}
return instance;
}
下来介绍饿汉式:
/**
* (饿汉式)
*/
public class Singleton {
/**
* Constructor:第一步 私有构造方法,防止被实例化
*/
private Singleton() {
}
/**
* 第二步 持有私有静态实例,防止被引用
* (和懒汉式不同,直接new一个。用static final修饰)
*/
private static final Singleton single = new Singleton();
/**
* 第三步提供对外 静态工厂方法
*/
public static Singleton getInstance() {
return single;
}
}
两种方法,都可以实现,那么到底选用那种方法实现呢?
个人认为,早创建和晚创建都得创建,简单,安全为主,所以优先考虑饿汉式.
(单例模式暂时就写到这里,其他模式看下面的帖子)