java中单例模式是一种常见的设计模式,单例模式分为三种:懒汉式单例、恶汉式单例和登记式单例。java
单例模式有如下特色设计模式
一、单例只能有一个实例安全
二、单例必须本身建立本身的惟一实例多线程
三、单例必须给其余对象提供惟一实例app
懒汉式单例线程
public class Singleton { private static Singleton single = new Singleton(); private Singleton(){}//私有化构造器 public static Singleton getInstance() { return single; } }
饿汉式单例设计
public class Singleton { private static Singleton single = null; private Singleton(){} public static Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; } }
在单线程环境下,上面的恶汉式不存在任何问题,但在多线程环境下,线程A和B,线程A第一次进入判断single为null,而后CPU切换到线程B,B判断single也为null,此时B线程会执行new Singleton(),而后CPU切回线程A,线程A继续执行也会new Singleton(),此时就会出现两个实例,问题就出来了。code
考虑到多线程环境下多线程安全问题,高效的饿汉式修改以下cdn
public class Singleton { private static Singleton single = null; private Singleton(){} public static Singleton getInstance() { //旨在避免实例化后其它线程在进入这个方法后进入同步代码块,提升效率 if (single != null) { return single; } synchronized (Singleton.class) { //第一个线程进入同步代码块,多个线程等待拿同步代码块的锁,进入同步代码块 //当第一个线程实例化,离开同步代码块后 //其它等待拿同步所的线程依次进入能够直接返回实例化对象 if (single != null) { return single; } single = new Singleton(); } return single; } }
若是须要进一步提升效率能够抛弃同步代码块使用Lock锁对象
public class Singleton { private static Singleton single = null; private Singleton(){} public static Singleton getInstance() { //旨在避免实例化后其它线程在进入这个方法后进入同步代码块,提升效率 if (single != null) { return single; } ReentrantLock lock = new ReentrantLock(false); try { lock.lock(); if (single != null) { return single; } single = new Singleton(); } catch (Exception e) { System.err.println(e.getMessage()); } finally { lock.unlock(); } return single; } }
登记式单例
等级是单例这个单例实际上维护的是一组单例类的实例(父类和子类),讲这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map中获取直接返回,对于没有登记的,则先登记,再返回。
@SuppressWarnings("unchecked") public class Singleton { @SuppressWarnings("rawtypes") private static HashMap map = new HashMap(); private Singleton (){} static { Singleton single = new Singleton(); map.put(single.getClass().getName(), single); } public static Singleton getInstance(String name) { if (name == null) { name = "Singleton"; } if (map.get(name) == null) { try { map.put(name, Class.forName(name).newInstance()); } catch (Exception e) { System.out.println("Error happened."); } } return (Singleton) map.get(name); } }
其子类实现
public class SingletonChild extends Singleton { private SingletonChild(){} public static SingletonChild getInstance() { return (SingletonChild) Singleton.getInstance("SingletonChild"); } }