1.单例设计模式
a.概述
- 单例设计模式是指某个类只有一个实例的设计模式。
- 特点:
-
- 1.构造函数是private修饰的,目的是防止用户调用构造函数创建对象
- 2.类的内部有静态工厂方法,返回该类的唯一实例。
- 3.类的唯一实例被private staic修饰的引用所修饰
-
b.单例分类
- 饿汉单例
-
/** * Created by yangyun on 2017/2/23. */ public class SingletonTest { //饿汉单例在类初始化的时候创建实例 private static SingletonTest instance=new SingletonTest(); private SingletonTest(){} public static SingletonTest getInstance(){ return instance; } }
- 特点:
-
- 优点:天生就是线程安全的,不用进行同步的处理
- 缺点:类加载的初始化阶段,会把类的staic字段放在clinit函数中进行执行,也就会初始化类的单例,这样做的缺点是无论是否会用到这个单例都会产生这个实例,有时候会浪费空间。
-
- 懒汉单例
-
public class SingletonTest { //饿汉单例在类初始化的时候创建实例 private static SingletonTest instance; private SingletonTest(){} public synchronized static SingletonTest getInstance(){ if(instance==null){ instance=new SingletonTest(); } return instance; } }
- 特点:
-
- 优点:考虑了线程安全,在特定的情况下可以节约内存
- 缺点:同步会影响效率,整个函数都是同步的,每次调用都需要等待其他线程释放锁
-
- 懒汉单例------改进
- 改进:仅仅同步创建对象的代码块
-
public class SingletonTest { //饿汉单例在类初始化的时候创建实例 private static SingletonTest instance; private SingletonTest(){} public static SingletonTest getInstance(){ if(instance==null) { synchronized (SingletonTest.class) { if (instance==null) { instance = new SingletonTest(); } } } return instance; } }
- 为什么两次判断instance==null
- 假设有两个线程在第一次判断后都为true,线程A先获取了对象锁,创建了对象后释放锁
- 第二个线程获取锁后,进行第二次instance==null的检查后,避免再次创建对象
c.反射与单例
-
/** * Created by yangyun on 2017/2/23. */ public class SingletonTest { //饿汉单例在类初始化的时候创建实例 private static SingletonTest instance; private SingletonTest(){} public static SingletonTest getInstance(){ if(instance==null) { synchronized (SingletonTest.class) { if (instance==null) { instance = new SingletonTest(); } } } return instance; } public static void main(String[] args){ try { SingletonTest instance1=SingletonTest.class.newInstance(); SingletonTest instance2=SingletonTest.getInstance(); System.out.println(instance1); System.out.println(instance2); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }//instace1、instance2的地址是不一样的,是两个对象
- 说明:
- 通过放射,可以调用类的构造函数,即使是private构造函数也是可以的
- 所以说在反射面前所有的单例设计模式都是失效的。