美文网首页
单例模式

单例模式

作者: 鉴闻俗说 | 来源:发表于2018-01-22 22:26 被阅读0次

一、什么是单例模式

单例模式是一种常用的软件设计模式。这种模式设计到一个单一的类,该类负责创建自己的对象,同时确保有且只有一个对象被创建,即一个类只有一个对象实例。并且这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象。

二、实现单例模式

单例模式通常有两种实现方式:懒汉式饿汉式

1、饿汉式。实现代码如下:

public class SingletonTest1
{
    public static void main(String[] args)
    {
        Singleton1 s1 = Singleton1.getInstance();
        Singleton1 s2 = Singleton1.getInstance();
        
        //判断s1和s2是否为同一个对象
        System.out.println(s1 == s2);
    }
}

/**
 * 单例模式实现方法之——饿汉式
 */
class Singleton1
{
    private static Singleton1 singleton1 = new Singleton1();
    
    private Singleton1(){}
    
    public static Singleton1 getInstance()
    {
        return singleton1;
    }
}

代码运行结果如下,可以发s1和s2为同一个对象:


image.png

说明:饿汉式方法实现单例模式是在类的内部实例化一个静态变量singleton1。并且该类的构造方法是私有的,因此在该类外部就不能创建新的实例了,还有该类为外部提供了得到唯一实例的静态方法getInstance()。

2、懒汉式,实现代码如下:

public class SingletonTest2
{
    public static void main(String[] args)
    {
        Singleton2 s1 = Singleton2.getInstance();
        Singleton2 s2 = Singleton2.getInstance();
        
        System.out.println(s1 == s2);
    }
}

class Singleton2
{
    private static Singleton2 singleton2;
    
    private Singleton2() {}
    
    public static Singleton2 getInstance()
    {
        if (singleton2 == null)
        {
            singleton2 = new Singleton2();
        }
        return singleton2;
    }
}

代码运行结果如下,可以发s1和s2为同一个对象:

image.png
说明:懒汉式也是通过一个类的静态变量实现的,但是并没有直接初始化。而是在函数getInstance()中实例化的,也就是每次想用的时候初始化的,如果之前已经初始化了,那就不会再初始化。但是懒汉式在多线程的情况下是线程不安全的

三、解决多线程下懒汉式线程不安全问题

1、首先看一下多线程下上述懒汉式中会出现生成不同实例的情况,这是因为如果线程A执行到了If(singleton == null),线程B执行到了Singleton = new Singleton();线程B虽然实例化了一个Singleton,但是对于线程A来说判断singleton还是木有初始化的,所以线程A还会对singleton进行初始化。代码如下:

public class SingleTest3
{
    public static void main(String[] args)
    {
        //新建两个线程并启动
        new MyThread().start();
        new MyThread().start();
    }
}

class Singleton3
{
    private static Singleton3 singleton3;
    
    private Singleton3() {}
    
    public static Singleton3 getInstance()
    {
        if (singleton3 == null)
        {
            singleton3 = new Singleton3();
        }
        return singleton3;
    }
}

//定义一个线程类
class MyThread extends Thread
{
    @Override
    public void run()
    {
        //输出单例
        System.out.println(Singleton3.getInstance());
    }
}

运行代码得到以下结果,明显两个线程得到的是不同的实例:


image.png

2、通过修改以上代码,解决懒汉式中的线程不安全问题

(1)使用同步方法,可以解决多线程下的线程安全问题:
class Singleton3
{
    private static Singleton3 singleton3;
    
    private Singleton3() {}
    
    public synchronized static Singleton3 getInstance()
    {
        if (singleton3 == null)
        {
            singleton3 = new Singleton3();
        }
        return singleton3;
    }
}
(2)
  • 使用同步声明,即synchronized代码块,这种情况下仍会出现线程不安全问题
class Singleton3
{
    private static Singleton3 singleton3;
    
    private Singleton3() {}
    
    public static Singleton3 getInstance()
    {
        if (singleton3 == null)
        {
            synchronized (Singleton3.class)
            {
                singleton3 = new Singleton3();
            }
            
        }
        return singleton3;
    }
}

说明:运行代码,发现仍然会出现生成不同实例的情况。这是因为如果线程A和B同时执行到了Synchronized(singleton.class),虽然也是只有一个线程能够执行,假如线程B先执行,线程B获得锁,线程B执行完之后,线程A获得锁,但是此时没有检查singleton是否为空就直接执行了,所以还会出现两个singleton实例的情况

  • 使用双重检查模式(DCL)解决同步声明中出现的线程不安全问题
class Singleton3
{
    private static Singleton3 singleton3;
    
    private Singleton3() {}
    
    public static Singleton3 getInstance()
    {
        if (singleton3 == null)
        {
            synchronized (Singleton3.class)
            {
                if (singleton3 == null)
                {
                    singleton3 = new Singleton3();
                }
                
            }   
        }
        return singleton3;
    }
}

相关文章

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

  • Telegram开源项目之单例模式

    NotificationCenter的单例模式 NotificationCenter的单例模式分析 这种单例模式是...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • IOS单例模式的底层原理

    单例介绍 本文源码下载地址 1.什么是单例 说到单例首先要提到单例模式,因为单例模式是单例存在的目的 单例模式是一...

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • 单例模式

    单例模式1 单例模式2

  • java的单例模式

    饿汉单例模式 懒汉单例模式

网友评论

      本文标题:单例模式

      本文链接:https://www.haomeiwen.com/subject/ommraxtx.html