设计模式之单例模式

设计模式之单例模式

何为单例模式?

简单的将就是只能存在一个实例对象。该类提供一个取得其对象的实例方法。

饿汉式(静态常量)

public class Test {
    public static void main(String[] args) {
        //测试
        Singleton singleton = Singleton.getSingleton();
        Singleton singleton2 = Singleton.getSingleton();
        System.out.println(singleton == singleton2);
        System.out.println(singleton.toString());
        System.out.println(singleton2.toString());
    }


}

class Singleton {
    private final static Singleton singleton = new Singleton();

    private Singleton() {
    }

    //通过静态方法
    public static Singleton getSingleton() {
        return singleton;
    }
}

可以看见,

优点在于此种写法比较简单,类加载就完成了实例化,避免了线程同步问题。

缺点是类加载时就实例化,没有达到懒加载效果。

可能造成内存浪费。

饿汉式(静态代码块)

class Singleton {
    private static Singleton singleton;

    static {
        singleton = new Singleton();
    }

    private Singleton() {
    }
    
    public static Singleton getSingleton() {
        return singleton;
    }
}

懒汉式(不安全)

用到的时候才创建。它是线程不安全的,只能在单线程下使用。

package cn.bubbletg.SingletonPattern.t01;

/**
 * @author www.bubbletg.cn * BubbleTg
 * @version 1.0
 * @date 2019/10/18 8:22
 * 

* 设计模式之单例模式 * 之懒汉式 */ public class Test01 { public static void main(String[] args) { //测试 Singleton singleton = Singleton.getSingleton(); Singleton singleton2= Singleton.getSingleton(); System.out.println(singleton==singleton2); System.out.println(singleton.toString()); System.out.println(singleton2.toString()); } } class Singleton { private static Singleton singleton; private Singleton() { } //通过静态方法 public static Singleton getSingleton() { /* *多线程下,if(singleton==null)可能被多个线程抢到执行,这时便会产生多个实例。 */ if (singleton == null) { singleton = new Singleton(); } return singleton; } }

运行结果:

true
cn.bubbletg.SingletonPattern.t01.Singleton@15db9742
cn.bubbletg.SingletonPattern.t01.Singleton@15db9742

因为是线程不安全的,我们对它加以改进。

懒汉式(安全)

对原来代码修改:

添加一个 synchronized 关键字。

解决了线程安全问题,但是效率太低了。

因为每次获取获取实例都要同步,然后方法只需要执行一次实例。

class Singleton {
    private static Singleton singleton;

    private Singleton() {
    }

    //添加一个synchronized
    //通过静态方法
    public static synchronized Singleton getSingleton() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

发现添加了安全,但是效率又不行了。我们再继续改进。

双重检测

解决了安全与效率的问题。

class Singleton {
  //用volatile 修饰
    private static volatile Singleton singleton;

    private Singleton() {
    }
    //通过静态方法
    public static Singleton getSingleton() {
        //1.多个线程来到这里,实例为空
       //4.后面执行就不用再多次同步了,效率提升
        if (singleton == null) {
            //2.多个线程到这里会等待。
            synchronized (Singleton.class) {
                //3.第一个线程进来创建后,其他进程无需再创建
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

静态内部类

class Singleton {
    private Singleton() {
    }
    private static class SingletonInstance {
        private static final Singleton SINGLETON = new Singleton();
    }
    public static Singleton getSingleton() {
        return SingletonInstance.SINGLETON;
    }
}

静态内部类方式在Singleton类装载是并不会立即实例化,而是在需要时候实例化,又因为是静态,只有第一次加载时候才初始化。没有线程安全问题。

枚举实现单例

public enum  SingletonPatternDemo05 {

    //这个枚举元素,本身就是单例
    INSTANCE;

    //添加自己需要的操作
    public void singletonOperation(){
    }
}
public static void SingletonPatternDemo05Test() {
        SingletonPatternDemo05 sp = SingletonPatternDemo05.INSTANCE;
        SingletonPatternDemo05 sp2 = SingletonPatternDemo05.INSTANCE;
        System.out.println("----枚举实现实现:--->");
        if (sp == sp2)
            System.out.println("两个实例相同!!-----sp =" + sp.toString() + "---sp2 =" + sp.toString());
        else
            System.out.println("两个实例相同!!-----sp =" + sp.toString() + "---sp2 =" + sp.toString());
    }

枚举方式可以实现单例模式,避免了多线程安全问题,还能防止反序列化。

你可能感兴趣的:(设计模式)