在Java开发中,有时我们会有这样的需求就是在描述一个类的时候,要求我们必须保证这个类的对象在内存中只会存在一个,就是保存对象在内存中的唯一性,那我们在设计这个类的时候,就应该使用单例设计模式。Java中常用的单例设计模式 有两种,懒汉式,饿汉式。采用单例设计模式设计的类有以下特点:
1,在该类中需要定义一个该类类型的静态字段。
2,将该类的构造函数私有化。
3,对外提供能够获取该类实例的静态工厂方法。
懒汉式:
- class Single
- {
-
- //定义一个静态的私有字段
- private static Single s=null;
-
-
- //定义静态工厂方法 返回该类的实例
- public static Single getSingleInstance()
- {
- if(s==null)
- {
- s=new Single();
- }
- return s;
- }
-
- //私化构造函数
- private Single()
- {
-
- }
- }
复制代码
饿汉式:
- class Single
- {
-
- //定义一个静态的私有字段, 并在类加载时候就创建了该类的实例
- private static final Single s=new Single();
-
-
- //定义静态工厂方法 返回该类的实例
- public static Single getSingleInstance()
- {
- return s;
- }
-
- //私化构造函数
- private Single()
- {
-
- }
- }
复制代码
懒汉式和饿汉式的区别:
1,饿汉式是在类加载的时候内存中就创建了对象,而懒汉式 是在调用该类的静态工厂方法的时候才创建对象。
2,饿汉式 是线程安全的,而懒汉式线程不安全。
分析懒汉式产生线程安全问题的原因:
当多个线程同时 执行懒汉式中的getSingleInstance()方法的时,这多个线程都会访问共享数据 静态私有字段s(因为该字段是静态的 所以是共享数据),并且操作共享数据的代码是多行,所以会产生线程安全问题,这样就保证不了该类在内存中的对象的唯一性。
解决懒汉式线程安全问题:
- class Single
- {
-
- //定义一个静态的私有字段
- private static Single s=null;
- //定义静态工厂方法 返回该类的实例
- public static Single getSingleInstance()
- {
- if(s==null)
- {
- synchronized(Single.class)
- {
- if(s==null)
- {
- s=new Single();
- }
- }
-
- }
- return s;
- }
-
- //私化构造函数
- private Single()
- {
-
- }
- }
复制代码
上面两种单例模式,能够保证对象的唯一性的根本原因就是 ,将构造函数私有化,不允许在该类的外部调用构造函数创建对象。要是我们利用反射技术Single.class.getDeclaredConstructor(null).setAccessible(true); 来获取到该类构造器对象 ,那么这样的话就保证不了对象的唯一性。所以说我们要是利用反射技术的话,上面两种单例模式就会失效。
PS:如果一个枚举类的枚举值只有一个话,这个枚举类可以当做单例设计模式使用。
|