单例设计模式和动态代理设计模式
解决的问题
一个应用范围内,一个class类,只应该存在一个对象。
单列设计模式的特点
1.构造私有(不能通过正常手段进行new对象—因为通过反射还可以私有的方法进行调用)
2.静态成员变量(存储单列对象的引用)
3.提供一个公开静态的访问方法,获取单列对象
两种方式
懒汉式:会存在线程安全问题(面试最常问的就是这个)
饿汉式:不存在线程安全问题
饿汉式和懒汉式的区别
饿汉式,是不管你用不用该对象,都创建。
——会照成资源的浪费。
——在创建对象的时候,不会出现多线程情况。
懒汉式,只有第一次访问的时候,才会创建。
——也叫延迟加载,由于被加载的时候,肯存在多线程访问,加上被访问的类中有成员变量。
单例模式常见的规范写法
1.双重检查锁(DCL)+volatile
2.静态内部类
饿汉模式的单列对象,什么时候创建?
当单例对象所对应的类被初始化的时候,才会创建该单例对象!!
类的初始化时机有哪些?通过new Student,通过访问static成员变量。。
在JVM加载类的时候,由JVM对加载类的线程加锁,也就是说类加载的时候,是线程安全的。不会存在线程安全问题。
如何判断线程安全问题?
1:是否存在多线程 是
2:是否有共享数据 是
3:是否存在非原子性操作 (是针对字节码指令)
原子性的理解
new Student(); i++;
是否是一个原子性操作呢? 不是的
如何保证原子性呢?加锁
volatile的第一个作用:可以禁用cpu缓存或者说工作内存
可见性的理解:
有序性的理解:
int x ; boolean a;
x= 20; step3 a = false; step4
x和a之间是没有依赖性(有没有happened-before关系)
所以说,JVM会考虑性能问题,有可能对step3和step4进行指令重排序。
int x = 10; int y ;
y = x+10;