首页 > 代码库 > Java设计模式の单例模式

Java设计模式の单例模式

--------------------------------------------------

目录

  1.定义

  2.常见的集中单例实现

    a.饿汉式,线程安全 但效率比较低

    b.单例模式的实现:饱汉式,非线程安全

    c.饱汉式,线程安全简单实现

    d.线程安全 并且效率高  单例模式最优方案

  3.总结

    a.使用枚举的单例模式

    b.使用枚举,static处调用,初始化一次

--------------------------------------------------

 

1.定义

确保一个类只有一个实例,并提供一个全局访问点!

2.常见的集中单例实现

  a.饿汉式,线程安全 但效率比较低

/**  * 单例模式的实现:饿汉式,线程安全 但效率比较低  */  public class SingletonTest {      // 定义一个私有的构造方法    private SingletonTest() {      }      // 将自身的实例对象设置为一个属性,并加上Static和final修饰符    private static final SingletonTest instance = new SingletonTest();      // 静态方法返回该类的实例    public static SingletonTest getInstancei() {          return instance;      }    }

  b.单例模式的实现:饱汉式,非线程安全   

/**   * 单例模式的实现:饱汉式,非线程安全    *    */  public class SingletonTest {    // 定义私有构造方法(防止通过 new SingletonTest()去实例化)    private SingletonTest() {       }       // 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)    private static SingletonTest instance;       // 定义一个静态的方法(调用时再初始化SingletonTest,但是多线程访问时,可能造成重复初始化问题)    public static SingletonTest getInstance() {           if (instance == null)               instance = new SingletonTest();           return instance;       }   } 

  c.饱汉式,线程安全简单实现  

/**   * 单例模式的实现:饱汉式,线程安全简单实现    *    */  public class SingletonTest {    // 定义私有构造方法(防止通过 new SingletonTest()去实例化)    private SingletonTest() {       }       // 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)    private static SingletonTest instance;       // 定义一个静态的方法(调用时再初始化SingletonTest,使用synchronized 避免多线程访问时,可能造成重的复初始化问题)    public static synchronized  SingletonTest getInstance() {           if (instance == null)               instance = new SingletonTest();           return instance;       }   } 

  d.线程安全 并且效率高  单例模式最优方案

/**   * 单例模式最优方案 * 线程安全  并且效率高   *   */  public class SingletonTest {     // 定义一个私有构造方法    private SingletonTest() {          }       //定义一个静态私有变量(不初始化,不使用final关键字,使用volatile保证了多线程访问时instance变量的可见性,避免了instance初始化时其他变量属性还没赋值完时,被另外线程调用)    private static volatile SingletonTest instance;      //定义一个共有的静态方法,返回该类型实例    public static SingletonTest getIstance() {         // 对象实例化时与否判断(不使用同步代码块,instance不等于null时,直接返回对象,提高运行效率)        if (instance == null) {            //同步代码块(对象未初始化时,使用同步代码块,保证多线程访问时对象在第一次创建后,不再重复被创建)            synchronized (SingletonTest.class) {                //未初始化,则初始instance变量                if (instance == null) {                    instance = new SingletonTest();                   }               }           }           return instance;       }   }

 

3.总结

  

  【以上单例模式】传统的两私有一公开(私有构造方法、私有静态实例(懒实例化/直接实例化)、公开的静态获取方法)涉及线程安全问题(即使有多重检查锁也可以通过反射破坏单例)

目前最为安全的实现单例的方法是通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次。如下

  a.使用枚举的单例模式

 

/** * 使用枚举的单例模式 * * @author yzl * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */public class EnumSingleton{    private EnumSingleton(){}    public static EnumSingleton getInstance(){        return Singleton.INSTANCE.getInstance();    }        private static enum Singleton{        INSTANCE;                private EnumSingleton singleton;        //JVM会保证此方法绝对只调用一次        private Singleton(){            singleton = new EnumSingleton();        }        public EnumSingleton getInstance(){            return singleton;        }    }}

  b.使用枚举,static处调用,初始化一次

import java.util.ArrayList;import java.util.List;/** * 初始化的优雅实现 * 可以在static处调用, * 也可以在普通方法里调用,都保证只初始化一次 *  * 当然将enum块的代码直接放到StaticInitTest类的private static 方法里做也是可以的 * * @author yzl * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */public class StaticInitTest {    private static List<Integer> dataList = null;        static{        dataList = Singleton.INSTANCE.init();    }        /**     *      * 单例模式来填充数据     *     * @author yzl     * @see [相关类/方法](可选)     * @since [产品/模块版本] (可选)     */    private static enum Singleton {        INSTANCE;        private List<Integer> list;                private Singleton(){            fillData();        }        /**         *          * 初始化数据         *         * @see [相关类/方法](可选)         * @since [产品/模块版本](可选)         */        private void fillData(){            list = new ArrayList<Integer>(5);            for(int i =1; i<6; i++){                list.add(i);            }        }        /**         *          * 初始化的入口         *         * @see [相关类/方法](可选)         * @since [产品/模块版本](可选)         */        public List<Integer> init(){            return list;        }    }}

 

参考资料:java单例之enum实现方式

 

     java设计模式--单例模式

Java设计模式の单例模式