单例,顾名思义,就是在整个系统中只有一个实例,就是单一、独苗的意思。
单例模式有三个要点:
一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
其中该类我们称之为:单例类。
持有单例对象的客户类,共享同一个单例对象,对其中的单例资源拥有同样的操作权限。比如邮局里的电话簿只有一本,有需要的人就拿来看,没有必要每个人要查的时候工作人员就重新拿出新的一本出来,看完了再回收。。。
使用单例模式的时机可以是:当实例存在多个会引起程序逻辑错误的时候,比如类似有序的号码生成器这样的东西,不可能让号码生成器从在多个。
具体实例如下:
1.预先加载法
class S1 {
private S1() {
System.out.println("ok1");
}
private finalstatic S1 instance =new S1();
publicstatic S1 getInstance() {
return instance;
}
}
优点:
1.线程安全的
2.在类加载的同时已经创建好一个静态对象,调用时反应速度快。
缺点: 资源利用效率不高,可能getInstance永远不会执行到,但是执行了该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化了
2.initialization on demand,延迟加载法 (考虑多线程)
class S2 {
private S2() {
System.out.println("ok2");
}
privatestatic S2 instance =null;
publicstaticsynchronized S2 getInstance() {
if (instance ==null) instance =new S2();
return instance;
}
}
优点:资源利用率高,不执行getInstance就不会被实例,可以执行该类其他静态方法。
缺点: 第一次加载时发应不快 ,多线程使用不必要的同步开销大
3.initialization on demand double check 双重检测(考虑多线程)
class S3 {
private S3() {
System.out.println("ok3");
}
privatestatic S3 instance =null;
publicstatic S3 getInstance() {
if (instance ==null) {
synchronized (S3.class) {
if (instance ==null)
instance = new S3();
}
}
return instance;
}
}
优点:资源利用率高, 不执行getInstance就不会被实例,可以执行该类其他静态方法。
缺点: 第一次加载时发应不快 ,由于java 内存模型一些原因偶尔会失败
4.initialization on demand holder (考虑多线程)
class S4 {
private S4() {
System.out.println("ok4");
}
private static class S4Holder {
static S4 instance = new S4();
}
public static S4 getInstance() {
return S4Holder.instance;
}
}
优点:资源利用率高, 不执行getInstance就不会被实例,可以执行该类其他静态方法。
缺点: 第一次加载时发应不快