您的位置:首页 > 其它

单例模式

2016-07-21 17:59 288 查看
基本上做程序的都知道单例模式,那么为什么要用单例模式了?

首先单例模式有几个关键点

1 构造函数不对外开放,一般为Private;(通过构造函数私有化,使得客户端代码不能通过new 的形式手动构造单例类的对象) 《在这就不能多次构建对象》

2 通过一个静态方法或者枚举返回单例类对象(客户端只能通过这个静态)

3 确保单例类的对象有且只有一个,尤其在多线程环境下 (明确多线程为什么会出现多个对象,因为虚拟机在分配线程的时候允许执行器乱序执行)(JVM 执行写的代码的是会把一个代码编译成多条汇编指令,然后乱序执行)

例如: String str = new String();

会执行大致3件事

1 给String 的实例分配对象

2 调用String() 的构造函数

3 江 str 对象指向分配的内存空间(此时Str 就不是null  了)

(执行顺序 可以是 1-2-3 也可以是 1-3-2)(JVM 1.5以后 官方修改了BUG 用了 volatile关键字)

4 确保单例类对象在反序列化时候不会重新构建对象

常见的几种单例模式

饿汉式(饿了就先吃,先创建对象)

public class A {

private static final A a = new A();

private A(){

   }

private static A getA(){]

        return a;

}

}

懒汉式

    

public class A {

private static  A a ;

private A(){

   }

private static syncyronized  A getA(){

if(a == null){

       a  = new A ();

}

        return a;

}

}

饿汉是线程安全的(没有在使用的时候就创建对象)  懒汉是线程不安全的所以得加同步锁  (备注 : 每次调用方法的时候使用同步锁会消耗不必要的资源,反应慢不建议使用 懒汉模式)

3  Double Check Lock (DCL) 实现单例

DCL 实现单例模式的有点是能够在需要的时候才创建对象 有能百战线程安全 且单例对象的时候可以不进行同步锁

优点 资源利用高 第一次执行getA 的时候才会被实例化  效率高 缺点 第一次加载的时候有点慢 也由于java 内存模型的原因偶尔会失败,在高发的环境下也有可能失败

public class A {
private static  A a = null ;
private A(){
   }
private static syncyronized  A getA(){
if(a == null){
synchronized ( A.class){
if(a == null){
a = new A();

 }

}
       a  = new A ();
}
        return a;
}
}
4  静态内部类单例模式
 这种方法在第一次加载类的时候并不会创建对象 只有第一次调用 getA 的时候才会导致虚拟机加载A 类 这种方式即保证对象的唯一性还能延迟单例的实力话 

public class A {
private A(){
   }
private static  A getA(){
        return AHolder.aHolder;
}
 private static class AHolder{
  private static final AHolder aHolder = new AHolder();

 }
}
5 推介使用的 枚举单例
枚举 最大的有点 默认创建的线程是安全的 并且在任何情况下都是单例
public enum A {
INSTANCE;
public void doSometing(){

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: