1.单例概念
单例模式是一种对象的创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例
2.单例优势
对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销,由于new操作的次数减少,因而对系统内存的使用频率也厚降低,这将降低GC压力,缩短GC停顿时间
3.单例书写步骤
- 构造方法私有化,保证在类的外部无法实例化该类的对象
- 定义静态私有对象
- 定义对外开放的静态方法,在调用方法时判断对象是否为空,为空再创建对象返回
4.单例的6种写法
- 饿汉式:无法对instance实例做延迟加载
- 懒汉式:多线程并发的情况下无法保证实例的唯一性
- 懒汉式线程安全:使用synchronized导致性能缺陷
- DCL:JVM即时编译器的指令重排序
- 静态内部类:延迟加载 / 线程安全 / 性能优势
- 枚举:在Java5之后才会出现,写法简单,线程安全
4.1 饿汉式:类加载的时候就实例化该类的对象
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
4.2 懒汉式
public class Singleton {
private Singleton{}
private static Singleton instance;
public static Singleton getInstance(){
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4.3 懒汉式线程安全
public class Singleton{
private Singleton{}
private static Singleton instance;
//方法上加synchronized关键字一般锁住的是当前对象,如果当前方法比较耗时在调用其他方法加锁的方法时会等待
//同步方法锁的范围比较大,而同步代码块范围要小点,一般同步的范围越大,性能就越差
//一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好
// 方法一:方法中声明synchronized关键字
public static synchronized Singleton getInstance(){
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 方法二:同步代码块中实现
public static Singleton getInstance(){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
return instance;
}
}
4.4 DCL
public class Singleton {
private Singleton(){}
//volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。
private static volatile Singleton instance;
public static Singleton getInstance(){
// 避免不必要的同步
if(instance == null){
synchronized(Singleton.class){
// 在第一次调用事初始化
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
4.5 静态内部类
public class Singleton{
private Singleton(){}
public static Singleton getInstance(){
return LazyHolder.instance;
}
private static class LazyHolder {
private static final Singleton instance = new Singleton();
}
}
4.6 枚举
public enum EnumSingleton{
// 定义一个枚举元素,它就是Singleton的一个实例
INSTANCE;
public void doSomething(){
}
}
5.单例的使用
- EventBus、ActivityManager、ImageLoader
- 判断连续点击工具类等
6.单例和静态方法
静态方法适合去完成一个独立的封闭的功能,所以如果方法中不需要维持一些外部的状态值,可以用静态方法的方式,否则做成单例的方式。
举例:在工具类里面有一些成员变量,假如有个boolean值,你的方法中需要判断或改变这个值,这种情况就是有外部状态的情况:例如 - 判断连续点击工具类需要改变时间
网友评论