单件模式确保一个类只有一个实例,并提供一个全局访问点。
作用:有一些常用来管理资源的对象(如线程池,数据库连接。。。)我们只需要一个,而事实上,这类对象这只能有一个,如果制造出多个实例,就会导致许多问题,比如,程序的行为异常,资源使用过量,或者是不一致的结果。
关键点:私有构造器,静态变量,静态方法
下面用一个例子来具体说一下:
public class Hachun
{
// 利用一个静态变量来记录Hachun类的唯一实例
private static Hachun UniqueInstance;
// 私有构造器,只有在Hachun类内才能调用构造器(即实例化该对象),防止其他地方随意创建
private Hachun(){}
// 此静态方法用来实例化Hachun对象,并返回这个实例,外部类可以通过该方法获得Hachun对象
public static Hachun getInstance()
{
// 只有当UniqueInstance为null时,才实例化,确保该对象只有一个
if (UniqueInstance==null)
{
UniqueInstance = new Hachun();
}
return UniqueInstance;
}
}
但这样可能会出现多线程的问题,从而导致异常,下面介绍一个处理该问题的方法:
修改getInstance()方法
public static synchronized Hachun getInstance()
{
if (UniqueInstance==null)
{
UniqueInstance = new Hachun();
}
return UniqueInstance;
}
通过添加关键字 synchronized,将迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法,也就是说,不会有两个线程同时进入这个方法,但,这个方法,会降低性能。
再看看另一个方法,急切实例化:
public class Hachun
{
// 保证线程安全
private static Hachun UniqueInstance = new Hachun();
private Hachun(){}
public static Hachun getInstance()
{
return UniqueInstance;
}
}
如果应用程序总是创建并使用这个单件实例,或者在创建和运行时方面的负担不是太繁重,上述方法比较适合。
如果你比较关心性能,试试 双重检查加锁(两个 if 检查判断) 方法:
public class Hachun
{
// volatile关键字确保 当UniqueInstance变量被初始化成 Hachun 实例时, 多个线程正确地处理UniqueInstance变量
private volatile static Hachun UniqueInstance;
private Hachun(){}
public static Hachun getInstance()
{
if (UniqueInstance==null)
{
// 同步区块,UniqueInstance若为null,则创建
synchronized(Hachun.class)
{
if (UniqueInstance==null)
{
UniqueInstance = new Hachun();
}
}
}
return UniqueInstance;
}
}