单例模式详解
单例模式是我们常见的,也是最简单的一种模式,比如我们Service。
整个程序中,只要用一个实例,就能解决所有问题,避免程序内存空间的消耗,我们就可以用到单例模式
什么情况下可以使用单例模式?
我们只想通过对象调用其方法,不需要针对不同对象设置不同的成员属性的时候,(就是不需要区分对象的差异时),我们就可以针对当前这个类,创建单例,在整个程序中使用当前类的同一个对象。
单例的五种模式
饿汉
缺点:如果一直没有使用的话,就对内存造成浪费
懒汉
这个里面使用到了两个关键字volatile和synchronized
当一个变量定义为 volatile 之后,将具备两种特性: 1.保证此变量对所有的线程的可见性,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。 2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)
synchronized是Java中的关键字,是一种同步锁。 修饰一个对象,一个程序调用这个对象; 其他试图访问该对象的线程将被阻塞。
静态内部类
静态内部类只会装载在一次,(在调用getInstance()方法时候,才会装在,来完成实例化)即是懒汉,也是线程安全
枚举
enum Singleton{
INSTANCE;//属性
public void method(){ System.out.println("ok"); }}
因为属性只用一个,就保证了单例、
基于CAS的单例模式
AtomicReference是作用是对”对象”进行原子操作。 提供了一种读和写都是原子性的对象引用变量。原子意味着多个线程试图改变同一个AtomicReference(例如比较和交换操作)将不会使得AtomicReference处于不一致的状态。
这种模式也是一种懒汉式。
jdk中源码的单例实现
Runtime在java中就是典型的单例
细节说明
单例模式保证了系统内存中只有一个对象,节省资源,提高性能
当想要实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,因为构造方法的私有
使用场景:需要频繁的创建和销毁对象,创建对象耗时多,耗资源多,但有经常用到的对象,比如工具类,数据源,等等