在有些系统中,为了节省内存资源、保证数据一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。
单例模式是设计模式中最简单的模式之一,通常一个类的构造函数是共有的,外部可以通过new 生成对应的实例, 但是,如果将类的构造函数设置为私有的,外部就无法调用,也就无法生成此类的实例,这时候,此类内部需要提供一个静态私有实例,并向外部提供一个静态的共有函数用于创建或者获取该静态私有实例。
说到单例模式,我们通常会联想到懒汉式跟饿汉式俩种实现形式。下面我们来分别说说这俩种模式。
1.懒汉式单例
该模式的特点是类加载的时候没有生成单例,只有当第一次调用getInstance方法的时候才回去创建这个单例,代码如下:
public class LazySingleton{
private static volatile LazySingleton instance=null;//保证instance在所有线程中同步
private LazySingleton(){ } //private避免类在外部被实例化
public static synchronized LazySingleton getInstance(){//getInstance方法前加同步
if(instance==null){
instance=new LazySingleton();
}
return instance;
}
}
有没有注意到代码中有俩个关键字,volatile、synchronized,这俩个关键字是保证线程安全的,如果是多线程模式,则不能删除这俩关键字,否则将存在线程非安全的问题,但是,加上这俩关键字,每次访问的时候都要同步,会影响性能,这正是懒汉式单例的缺点。
2.饿汉式单例
该模式的特点是类加载的时候就创建了一个单例,保证在调用getInstance方法之前单例就已经存在了。代码如下:
public class HungrySingleton{
private static final HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){ }
public static HungrySingleton getInstance(){
return instance;
}
}
饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。
适用场景
1.当对象需要被共享的时候。由于单例模式只允许创建一个实例,共享该对象可以节省内存,并加快独享的访问速度。如web中的配置对象、数据库连接池等。
2.当某类需要频繁实例化,而创建爱你的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
模式扩展
单例模式可以扩展成有限的多例模式,这种模式可以生成有限个实例并保存在列表中,可以随机获取,有兴趣的可以查找相关资料了解。
分享是种乐趣~~~写BUG也是