大话设计模式读书笔记(单例模式)

人物:大鸟,小菜

事件:小菜在点击一个小工具的图标时,每次点击都会创建一个窗体,但是小菜希望的是,第一次点击新建一个窗体,但是后面的每次点击都只会弹出以前创建的那个窗体,小菜很郁闷,于是大鸟让小菜借此学习单例模式。


单例模式:

1.简介单例模式,并讲述了单例模式的懒汉式

2.介绍了单例模式的饿汉式

 

单例模式(懒汉式)

1.概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2.特点:单例模式只能有一个实例;单例类必须创建自己的唯一实例;单例类可以为其他类提供这一实例

3.懒汉式基础代码实现:

Singleton类,即单例类:

public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

客户端:

@Slf4j
public class SingletonClient {
    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();

        if (s1 == s2) {
            log.info("两个对象是相同的实例");
        }
    }
}

输出结果:

两个对象是相同的实例

 

4.多线程下怎么保证单例模式线程安全,即加锁

注意:在多线程中,可能多个线程同时访问Singleton类,为了避免创建多个实例,加锁如下:

public class Singleton {
    private static Singleton instance;
    private static final Object lock = new Object();

    private Singleton() {
    }

    public static Singleton getInstance() {
        synchronized (lock) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

小菜:那这样不是会每次都加锁么,可能没有创建实例也直接加锁了?

大鸟:那还可以做如下改动,先判断实例是否为空,再看锁不锁

 

5.实现双重锁定如下:

public class Singleton {
    private static Singleton instance;
    private static final Object lock = new Object();

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

 

6.静态内部类,保证线程安全由提高点性能:

public class Singleton {

    private Singleton() {
    }

    private static class LazyHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return LazyHolder.instance;
    }
}

问:为什么静态内部类是线程安全的?

答:利用了类中静态变量的唯一性,而且不加锁性能会好很多

 

单例模式(饿汉式)

public class Singleton {

    private Singleton() {
    }

    private static final Singleton single = new Singleton();

    public static Singleton getInstance() {
        return single;
    }
}

问:为什么这种方式是线程安全的?

答:在类创建的时候,也会创建类里面的静态对象,而静态对象一旦创建,又利用了静态变量的唯一性,和懒汉式的静态内部类有些相似

问:那静态内部类和饿汉式有什么区别呢?

答:静态内部类,需要时才加载类中的方法,又因为饿汉式里一开始就将静态变量加载,所以使用上的性能可能没有饿汉式的好

      饿汉式,第一次加载类时直接就将静态变量加载了,但是如果后面一直不使用,就会造成内存的浪费

 

posted @ 2020-08-06 10:52  pmingup9012  阅读(96)  评论(0编辑  收藏  举报