单例设计模式
单例模式的定义
确保某一个类只产生一个实例,而且自行实例化并向整个系统提供这个实例。
Ensure a class has only one instance,and provider a global point of access to it.
单例模式的优点:
1.减少内存开支,特别是一个对象频繁创建和销毁而其过程又无法通过性能优化达到需求,单例模式优势更加明显,因为其在内存中只有一个实例。
2.减少系统性能开销,如果一个对象的实例化需要加载很多的资源和配置,那么频繁的创建就会给系统带来较大的开销。可以通过单例的模式来使实例永久的驻存在内存中。
3.对实例的生命周期可控。
4.可以避免对资源的多重占用。对一个资源的操作始终只有一个实例在进行。
5.可以一在系统设置全局的访问点。
单例模式的缺点:
1.扩展困难。
2.生命周期过长。
3.在并行环境中对不便测试。
单例模式的应用场景:
1.应用中只能拥有一个该类的实例,如果存在多个会出现问题。
2.需要公共的访问空间,数据存储。
3.创建一个对象需要消耗的资源过多。
4.需要对实例的生命周期可控制。
单例模式的通用类图如图1-1所示
图1-1
单例模式的核心是确保一个类只有一个实例;那么该如何保证?我们知道一个实例的产生需要同过构造函数的,那么我们就可以通过限制构造函数的访问权限来达到这个目的。 通过是用 private关键字修饰的构造函数确保了在一个应用中只产生一个实例。
详细的代码清单如图1-2(这种写法被称为饿汉式)
public class SinglePubMode{
//自行实例化
private static final SinglePubMode instance=new SinglePubMode();
//构造函数私有化,限制产生多个对象
private SinglePubMode(){
}
//通过该方法获得实例
public static SinglePubMode getInstance(){
return instance;
}
}
单例模式的线程同步问题
例1:线程不安全的例子
public class Singleton{
public static Singleton instance=null;
private Singleton(){}
public static Singleton getInstance(){
if(instance!=null){
instance=new Singleton();
}
return instance;
}
}
在并发量小的情况下还可以,如果并发量过大可能会造成多个实例。原因在于当一个线程执行到instance=new Singleton();这行代码时,但是还没有创建实例,这时如果另一线程执行到if(instance!=null)那么这时候就会出现多个实例的问题。
解决办法加上synchronized关键字
懒汉式
public class Singleton{
public static Singleton instance=null;
private Singleton(){}
//第一种
public static synchronized Singleton getInstance(){
if(instance!=null){
instance=new Singleton();
}
//第二种 双重判定
public static Singleton getInstance(){
if(instance!=null{
synchronized)Singleton.class){
if(instance!=null){
instance=new Singleton();
}
}
}
}
return instance;
虽然可以解决线程同步的问题,但是却会影响性能,所以并不是最好的单例模式。如果初始化实例时消耗不是很大推荐使用饿汉式,如果消耗很大而且同一时间有很多的初始化操作好做那么可以尝试使用懒汉式。