Java单例模式的写法

来源:互联网 发布:java导出pdf 编辑:程序博客网 时间:2024/04/29 05:48

第一种写法: 懒汉式单例


class Singleton{private static Singleton singleleton=null;pulic static Singleton getInstance(){if(singleleton==null){    singleleton=new Singleton()    }return singleleton;}private Singleton(){singleleton=new Singleton();    }}

特点:这种写法是线程不安全的,他无法保证同时不被多个线程访问,适合在单线程环境下使用。

要想保证线程安全,可以参考下面三种写法:

1)使用synchronized关键字


class Singleton{private static Singleton singleleton=null;pulic static synchronized Singleton getInstance(){if(singleleton==null){    singleleton=new Singleton()}return singleleton;}private Singleton(){singleleton=new Singleton();}}

特点:相比上个方法,在静态方法前多加了个synchronized关键字,使同一时间只能有一个线程访问该代码块。

2)双重检查锁定


class Singleton{private static Singleton singleleton=null;pulic static Singleton getInstance(){if(singleleton==null){    synchronized(Singleton.class){    if(singleleton==null){        singleleton=new Singleton();        }    }}return singleleton;}private Singleton(){singleleton=new Singleton();}}

特点:经过两次判定,第一次检测到实例为空时,增加同步,同步后再次检测到实例为空时,才创建对象实例。有效防止了在多线程环境下创建多个实例的问题。

3)静态内部类实现


class Singleton{private singleton(){}private static class SingleBuilder{    private static Singleton singleton=new Singleton();          //就像private int int=1}public static Singleton getInstance(){    return SingleBuilder.singleton;}}

特点:Java中静态内部类可以访问其外部类的成员属性和方法,同时java规定静态内部类只在首次调用时被加载,因此实现了懒汉式,所以他只被加载一次,所以是线程安全的


2.饿汉式:


class Singleton{private static Singleton singleleton=new Singleton();pulic static Singleton getInstance(){return singleleton;}private Singleton(){}}

特点:饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。


3.登记式:


public class Singleton {  private static Map< String,Singleton> map = new HashMap< String,Singleton>();  static{      Singleton single = new Singleton();      map.put(single.getClass().getName(), single);  }  //保护的默认构造子  protected Singleton(){}  //静态工厂方法,返还此类惟一的实例  public static Singleton getInstance(String name) {      if(name == null) {          name = Singleton.class.getName();          System.out.println("name == null"+"--->name="+name);      }      if(map.get(name) == null) {          try {              map.put(name, (Singleton) Class.forName(name).newInstance());          } catch (InstantiationException e) {              e.printStackTrace();          } catch (IllegalAccessException e) {              e.printStackTrace();          } catch (ClassNotFoundException e) {              e.printStackTrace();          }      }      return map.get(name);  }  public static void main(String[] args) {      Singleton3 single = Singleton.getInstance(null);  }  }  

登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。 内部实现还是用的饿汉式单例。

4.使用volatile 关键字


class Singleton{ private static volatile Singleton Instance=null; public Singleton() { } public static Singleton getInstance(){   if(Instance==null){       synchronized (Singleton.class) {           if (Instance == null) {               Instance = new Singleton();           }       }   }    return Instance;  }}

volatile 保证在实例对象创建后快速通知其他线程该对象的实例已经存在,不需要重复创建了。

1 0
原创粉丝点击