饿汉模式
public class HungryMode { private static HungryMode hm = new HungryMode(); private HungryMode() { System.out.println("creat hungryMode Instance"); } public static HungryMode getInstance() { return hm; } public static void ceshi() { System.out.println("ceshi"); } public static void main(String[] args) { HungryMode.ceshi(); } }
饿汉式单例,就是一个私有的构造方法加一个私有的静态当前类实例对象和一个公有的静态获取实例方法组成因为类实例对象为静态变量,因此在加载类的时候咱们就会建立类的实例对象,这样的话比较消耗内存,浪费性能。 html
懒汉模式
public class LazyMode { private static LazyMode aLazyMode; private LazyMode() { System.out.println("create LazyMode Instance"); } public static LazyMode getInstance() { if(aLazyMode==null) { aLazyMode = new LazyMode(); } return aLazyMode; } public static void main(String[] args) { LazyMode.getInstance(); } }
懒汉式在饿汉式的基础上作了改进,类实例对象作了懒加载,也就是所谓的延时加载,因此提高了一些性能。编程
多线程的单例
以上的写法在单线程的编程环境中没有什么问题,可是若是是多个线程使用上面的单例模式就会违背单例模式的设计原则,出现多个对象,简单的作法是在获取类实例的方法上加同步锁,而且给类实例对象加上volatile修饰符,volatile能保证对象的可见性,即在工做内存的内容更新能当即在主内存中可见。工做内存是线程独有的内存,主内存是全部线程共享的内存。还有一个做用是禁止指令重排序优化。你们知道咱们写的代码(尤为是多线程代码),因为编译器优化,在实际执行的时候可能与咱们编写的顺序不一样。编译器只保证程序执行结果与源代码相同,却不保证明际指令的顺序与源代码相同。这在单线程看起来没什么问题,然而一旦引入多线程,这种乱序就可能致使严重问题。volatile关键字就能够从语义上解决这个问题。由于同步锁的机制,多个线程获取类实例对象会排队等待获取锁,这样是不必的,由于大多数状况下类实例对象都已经建立成功了,因此不用进入加锁的代码块,因而就能够再次改进上面的代码为双重校验的单例模式,如代码所示多线程
/** * 多线程的单例模式,使用双重校验机制 */ public class DoubleCheckMode { private volatile static DoubleCheckMode sDoubleCheckMode ; public DoubleCheckMode() { System.out.println(" created " + getClass().getSimpleName()); } public static DoubleCheckMode getInstance() { if (sDoubleCheckMode == null) synchronized (DoubleCheckMode.class) { if (sDoubleCheckMode == null) { sDoubleCheckMode = new DoubleCheckMode(); } } return sDoubleCheckMode; } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread() { @Override public void run() { super.run(); System.out.println("thread" + getId()); DoubleCheckMode.getInstance(); } }.start(); } } }
使用静态内部类实例单例
这种实现就是利用静态类只会加载一次的机制,使用静态内部类持有单例对象,达到单例的效果,直接上代码吧ide
/** * 静态内部类的方式实现单例,能够保证多线程的对象惟一性,还有提高性能,不用同步锁机制 */ public class InnerStaticMode { private static class SingleTonHolder { public static InnerStaticMode sInnerStaticMode = new InnerStaticMode(); } public static InnerStaticMode getInstance(){ return SingleTonHolder.sInnerStaticMode; } }
使用枚举实现单例性能
public enum EnumMode { INSTANCE; private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } }
总结
枚举实现单例,不推荐在Android平台使用,由于内存消耗会其余方式多一些,Android官方也不推荐枚举,Android平台推荐双重校验或者静态内部类单例,如今的Android开发环境jdk通常都大于1.5了。因此volatile的问题没必要担忧。Java平台开发的Effective Java一书中推荐使用枚举实现单例,能够保证效率,并且还能解决反序列化建立新对象的问题。优化