-
简介:
- 单例模式(Singleton)是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例的特殊类。
-
定义:
- 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
-
单例模式
-
单例模式根据实例化对象时机不同分为两种模式。
- 饿汉式:饿汉式单例在单例类被加载的时候,就实例化一个对象交给自己引用
- 懒汉式:懒汉式单例在调用取得实例方法的时候才会被实例化对象。
代码如下:
-
package com.lvsling.test; /** * 单例模式 * @author Administrator * */ public class TestSingleton { public static void main(String[] args) {
//验证ClassA是单例 ClassA a1 = ClassA.newInstance(); ClassA a2 = ClassA.newInstance(); System.out.println(a1 == a2);//true:单例
//验证ClassB是单例 ClassB b1 = ClassB.newInstance(); ClassB b2 = ClassB.newInstance(); System.out.println(b1 == b2);//true:单例
//验证ClassC是单例 ClassC c1 = ClassC.newInstance(); ClassC c2 = ClassC.newInstance(); System.out.println(c1 == c2);//true:单例
} } //饿汉式 class ClassA{ private static ClassA instance = new ClassA(); public static ClassA newInstance(){ return instance; } private ClassA(){
} } //懒汉式 class ClassB{ private static ClassB instance = null; public static synchronized ClassB newInstance(){ if (instance == null) instance= new ClassB(); return instance; } private ClassB(){
} } //静态内部类:既实现了线程安全,又避免了同步带来的性能影响。 class ClassC{ private static class Holder{ public static ClassC instance = new ClassC(); } public static ClassC newInstance(){ return Holder.instance; } private ClassC(){
} } |
-
饿汉式和懒汉式的区别
-
从饿汉,懒汉来看:
- 饿汉式的类一旦加载,就把单例初始化完成,饿汉式创建单例是写在static修饰的静态属性后。
- 懒汉式static修饰的静态属性创建一个null的空间,当调用newInstance的时候,才回去初始化单例
-
从线程安全的角度:
- 饿汉式天生就是线程安全的
- 懒汉式本身并非线程安全,实现线程安全而采用synchronized锁标记,或者静态内部内的方法
-
从性能方面:
- 饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占用一些内存,但是,如果在第一次调用使用时速度会很快因为它在类加载的时候已经创建好了,单例已经存在了
- 懒汉式因为调用newInstance才会去实例化对象,所以第一次调用时性能会延迟,但是懒汉式不会浪费内存,用到时才会创建单例对象。
-
-
单例模式的优点:
- 防止其它对象对自己的实例化,确保所有的对象都访问一个实例 。
- 提供了对唯一实例的受控访问。
- 由于在系统内存中只存在一个对象,因此可以节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
- 避免对共享资源的多重占用。
-
单例模式的适用场景:
- 需要频繁实例化然后销毁的对象。
- .创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
- 有状态的工具类对象。
- 频繁访问数据库或文件的对象。
-
总结:
- 我认为,在使用单例模式时,如果不考虑资源的使用,可以采用饿汉式,在使用的时候更快更迅速。
- 如果考虑资源的浪费,可以采用静态内部内的方式去实现。
- 单例模式其核心思想就是将构造方法私有化,通过静态方法获取一个唯一的实例
- 在获取的过程中,既要保证线程安全,又要防止反序列化导致重新生成实例对象。