单例模式


一、        定义

单例模式(Singleton Pattern):Ensure a class has only one instance,and provide a global point ofaccess to it.

其主要作用是控制某个类型的实例数量有且只有一个,即本质是控制实例数目。

二、        实现方式

1.     饿汉式单例

特点:类加载时实例化,其优点是线程安全

public class Singleton{

      //在类初始化时,已经自行实例化
             private static final Singleton instance = new Singleton();

         privateSingleton() {}//避免了类在外部被实例化

         public static SingletongetInstance() {

                   return instance;

         }

}

(注:通过Java反射机制是能够实例化构造方法为private的类,那基本上会使所有的Java单例实现失效。)

2.     懒汉式单例

特点:在第一次调用时实例化 ,其优点是延迟加载

此实现方式体现了延迟加载的思想(Lazy Load,开始不加载资源和数据,使用时才加载),同时也体现了缓存的思想。

public class Singleton{

     private static Singletoninstance = null;

     privateSingleton() {}

     public static synchronized SingletongetInstance() {//保证线程安全,但会降低速度

              if (instance == null) {

                       instance = newSingleton();

              }

              return instance;

     }

}

优化:使用双重检查加锁方法改进,只在第一次创建实例时同步,以后不需要同步,从而加快运行速度。

public class Singleton2{

     //volatile不会被本地线程缓存,对变量的读写直接操作共享内存

     private volatile static Singleton2instance = null;

     privateSingleton2() {}

     public static Singleton2getInstance() {//双重检查加锁

              if (instance == null) {//整个过程只需要一次同步

                       //同步块,线程安全的创建实例

                       synchronized(Singleton2.class) {

                                 if (instance == null) {

                                          instance= new Singleton2();

                                 }

                       }

              }

              return instance;

     }

}

 

3.     登记式单例

 

import java.util.HashMap;

import java.util.Map;

//类似Spring里面的方法,将类名注册,下次从里面直接获取。

public class Singleton3{

    private staticMap<String,Singleton3> map = newHashMap<String,Singleton3>();

    static{

        Singleton3 single = new Singleton3();

        map.put(single.getClass().getName(),single);

    protected Singleton3(){}//保护的默认构造子

    //静态工厂方法,返还此类惟一的实例

    public static Singleton3getInstance(String name) {

        if(name == null) {

            name = Singleton3.class.getName();

            System.out.println("name== null"+"--->name="+name);

        }

        if(map.get(name)== null) {

            try {

                map.put(name,(Singleton3) Class.forName(name).newInstance());

            } catch(InstantiationException e) {

                e.printStackTrace();

            } catch(IllegalAccessException e) {

                e.printStackTrace();

            } catch(ClassNotFoundException e) {

                e.printStackTrace();

            }

        }

        return map.get(name);

    }

    public Stringabout() {  

        return "Hello,I am RegSingleton.";   

    }   

    public static voidmain(String[] args) {

        Singleton single = Singleton.getInstance(null);

        System.out.println(single3.about());

    }

}

4.     即实现延迟加载,又保证线程安全,使用Lazy initialization holder class模式

此方法综合使用了Java的类级内部类和多线程默认的同步锁,巧妙地实现了延迟加载和线程安全。

public class Singleton4{

         /**

          * 类级的内部类,即静态的成员内部类,该内部类的实例与外部类的实例没有绑定关系,只有被调用时才装载,从而实现延迟加载

          */

         private static classSingletonHolder {

                   /*

                    * 静态初始化器,由JVM来保证线程安全

                    */

                   private static Singleton4instance = new Singleton4();

         }

         privateSingleton4() {}

         public static Singleton4getInstance() {

                   returnSingletonHolder.instance;

         }

}

5.     利用缓存来实现单例模式

利用缓存的基本知识,每次都先从缓存中取值,只要创建过一次对象实例后就设置了缓存的值,那么下次就不需要在创建了。(再次先不考虑多线程的问题)

public class Singleton5{

         private final static String D_KEY = "one";

         privateSingleton5() {}

         // 缓存实例的容器

         private staticMap<String, Singleton5> map = newHashMap<String, Singleton5>();

         public static Singleton5getInstance() {

                   Singleton5 instance = map.get(D_KEY);

                   if (instance== null) {

                            instance = new Singleton5();

                            map.put(D_KEY,instance);

                   }

                   return instance;

         }

}

6.     单例和枚举

单元素的枚举类型是实现Singleton的最佳方法,Java中枚举类型除了不能继承外,和普通类没区别。使用枚举实现单例控制,更简单、高效、安全。

public enum Singleton6{

         uniqueInstance;//只定义一个枚举的元素,它代表Singleton的一个实例

         public voidsingletonOperation(){

                   //功能处理

         }

}

三、        应用

1.优点:在内存只有一个实例,减少内存消耗,减少系统的性能开销,避免多资源的多重占用。

2. 在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。

    3.单例模式扩展,如有上限的多例模式。

    4.一个应用实例:

public classConfigManager {

         private static final String FIFLE = "d://data/user.properties";

         private File file = null;

         private long lastModifiedTime = 0;

         private Propertiesprops = null;

         private staticConfigManager instance = newConfigManager();

         privateConfigManager() {

                   file = new File(FIFLE);

                   lastModifiedTime = file.lastModified();

                   if (lastModifiedTime == 0) {

                            System.out.println(FIFLE + "file does not exist!");

                   }

                   props = newProperties();

                   try {

                            props.load(newFileInputStream(FIFLE));

                   } catch(IOException e) {

                            e.printStackTrace();

                   }

         }

         /*

          * 静态工厂方法

          */

         public static synchronized ConfigManagergetInstance() {

                   return instance;

         }

         /*

          * 获取属性配置项的值

          */

         public final ObjectgetConfigItem(String name, Object defaultVal) {

                   long newTime = file.lastModified();

                   if (newTime== 0) {

                            // 属性文件不存在

                            if (lastModifiedTime == 0) {

                                     System.out.println(FIFLE + "file does not exist!");

                            } else {

                                     System.out.println(FIFLE + "file was deleted!");

                            }

                            return defaultVal;

                   } else if (newTime> lastModifiedTime) {

                            props.clear();

                            try {

                                     props.load(newFileInputStream(FIFLE));

                            } catch(IOException e) {

                                     e.printStackTrace();

                            }

                   }

                   lastModifiedTime = newTime;

                   Object val = props.getProperty(name);

                   if (val == null) {

                            return defaultVal;

                   } else {

                            return val;

                   }

         }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值