Java设计模式-单例模式

来源:互联网 发布:weex playground 源码 编辑:程序博客网 时间:2024/06/08 18:20
1:使用场景

     确保某个类有且仅有一个对象的场景,避免产生多个对象消耗过多资源。例如:访问io和数据库资源,这时就要考虑使用单例模式。

2:UML图

      

        关键点:

        1:构造方法为private(该类不能通过new的方式产生对象)

        2:   通过静态方法或枚举返回单例对象

        3:确保在多线程环境下,产生的对象只有一个

        4:确保单例对象在反序列化时,不会产生新对象


3:代码举例

3.1  饿汉模式:

public class Singleton2{private Singleton2(){}private static final Singleton2 single2=new Singleton2();public static Singleton2 getInSingleton2(){return  single2;}}


3.2 懒汉模式:

1)原始:

public class Singleton {//1: 懒汉模式,在类第一次调用自己时实例化自己private Singleton(){}private static Singleton singleton=null;/** * 有线程安全问题 * @return */public static Singleton getInstance(){if(singleton==null){    singleton=new Singleton();}return singleton;}}


2)解决方案1:

public class Singleton {//1: 懒汉模式,在类第一次调用自己时实例化自己private Singleton(){}private static Singleton singleton=null;/** * 好像性能有些问题 * @return */public static synchronized Singleton getInstance(){if(singleton==null){singleton=new Singleton();}return singleton;}}


3)解决方案2:DCL-双重检查锁定

public class Singleton {//1: 懒汉模式,在类第一次调用自己时实例化自己private Singleton(){}private static Singleton singleton=null;public static Singleton getInstance(){if(singleton==null){synchronized (Singleton.class) {if(singleton==null){singleton=new Singleton();//1}}}return singleton;}}
 

双重检查锁定(DCL)-存在指令重排序的问题:

注释1处:可能指令重排序,导致有一个线程会获取一个初始化一半的singleton,应该private volatile static Singleton singleton=null;


singleton=new Singleton();

a: 给Singleton实例分配堆内存

b: 调用Singleton构造函数

c: 将singleton指向分配的内存空间


b依赖于a,c依赖于a,b,c之间无依赖,导致执行顺序:

a-b-c: 没毛病

a-c-b:

刚好执行完a-c,这时,线程切换到别的线程,这时singleton非空,执行会有问题,不好排查


解决办法:

private volatile static Singleton singleton=null;


volatile详解:

4)静态内部类单例模式:

public class Singleton1{private static class LazyHolder{private static final Singleton1 INSTANCE=new Singleton1();}private Singleton1(){}public static final Singleton1 getInstance(){return LazyHolder.INSTANCE;}}

3.3 枚举方式

public enum SingletonEnum {    INSTANCE;    private Person person=new Person();    public Person getPerson() {        return person;    }    public class  Person{    }}


3.4 反序列化

public class Singleton  implements Serializable{private static final long serialVersionUID=-1L;protected Object readResolve() {return singleton;}


public  class SaveAndRead {public  static void main(String[] args){Singleton mSingleton= Singleton.getInstance();System.out.println("序列化前对象:"+mSingleton.hashCode());try {FileOutputStream fos=new FileOutputStream(new File("123.txt"));ObjectOutputStream oos =new ObjectOutputStream(fos);oos.writeObject(mSingleton);oos.close();fos.close();} catch (Exception e) {e.printStackTrace();}try {FileInputStream fis =new FileInputStream(new File("123.txt"));ObjectInputStream ois =new ObjectInputStream(fis);Singleton singleton=(Singleton)ois.readObject();ois.close();fis.close();System.out.println("反序列化后对象:"+singleton.hashCode());} catch (Exception e) {}    }}



3.5 容器单例模式

public class SingletonManager{private static Map<String, Object> objMap=new HashMap<String, Object>();private SingletonManager(){}public static void addService(String key, Object instance){if(!objMap.containsKey(key)){objMap.put(key, instance);}}        public static Object getService(String key){return objMap.get(key);}}



4:android中的单例模式

4.1  frameworks/base/core/java/android/view/accessibility/AccessibilityManager.java

/**     * Get an AccessibilityManager instance (create one if necessary).     *     * @param context Context in which this manager operates.     *     * @hide     */    public static AccessibilityManager getInstance(Context context) {        synchronized (sInstanceSync) {            if (sInstance == null) {                final int userId;                if (Binder.getCallingUid() == Process.SYSTEM_UID                        || context.checkCallingOrSelfPermission(                                Manifest.permission.INTERACT_ACROSS_USERS)                                        == PackageManager.PERMISSION_GRANTED                        || context.checkCallingOrSelfPermission(                                Manifest.permission.INTERACT_ACROSS_USERS_FULL)                                        == PackageManager.PERMISSION_GRANTED) {                    userId = UserHandle.USER_CURRENT;                } else {                    userId = UserHandle.myUserId();                }                sInstance = new AccessibilityManager(context, null, userId);            }        }        return sInstance;    }


4.2 frameworks/base/core/java/android/text/Editable.java


原创粉丝点击