前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >创建型模式————单例模式(2.1)

创建型模式————单例模式(2.1)

作者头像
Noneplus
发布2019-09-24 16:03:13
2860
发布2019-09-24 16:03:13
举报
文章被收录于专栏:开发笔记

单例模式定义

在软件系统中,一个类只有一个实例对象。(该类只提供一个取得实例的静态方法)

推荐使用的三种单例模式

  • DoubleCheck
  • 静态内部类
  • 枚举

1.DoubleCheck 双重检查

特点:效率高,线程安全,延迟加载。

代码语言:javascript
复制
class DoubleCheck
{
    private static volatile DoubleCheck instance;

    private DoubleCheck(){}

    public static DoubleCheck getInstance()
    {
        /*
        DoubleCheck如何实现?线程安全和效率提升
        
        在多线程的环境下,假设线程A直接进入#2,实例化对象。
        且实例化方法外用synchronized修饰,所以是线程安全的。
        当线程A实例化对象结束,对象instance已经被创建,执行到#1的线程将会直接调到#3,返回instance
        
        且DoubleCheck实现了延迟加载(new在方法里)
         */
        if(instance==null)                               //#1
        {
            synchronized (DoubleCheck.class)             //#2
            {
                if(instance==null)
                {
                    instance = new DoubleCheck();        //#3
                }
            }
        }
        return instance;
    }
}


public class Operation
{
    public static void main(String[] args) {
        DoubleCheck doubleCheck1 = DoubleCheck.getInstance();
        DoubleCheck doubleCheck2 = DoubleCheck.getInstance();

        System.out.println(doubleCheck1.hashCode());
        System.out.println(doubleCheck2.hashCode());


    }
}

2.静态内部类

特点:通过JVM类加载避免了线程安全问题,延迟加载,效率高。

代码语言:javascript
复制
class StaticClassInner {

    private StaticClassInner() {}



    /*
     使用静态内部类,实现了延迟加载
     调用getInstance()方法时,才会加载StaticClassInnerInstance。

     通过JVM类加载线程安全的机制,避免了线程不安全。

     */
    private static class StaticClassInnerInstance {
        private static final StaticClassInner INSTANCE = new StaticClassInner();
    }

    public static StaticClassInner getInstance() {
        return StaticClassInnerInstance.INSTANCE;
    }
}

public class Operation
{
    public static void main(String[] args) {
        StaticClassInner doubleCheck1 = StaticClassInner.getInstance();
        StaticClassInner doubleCheck2 = StaticClassInner.getInstance();

        System.out.println(doubleCheck1.hashCode());
        System.out.println(doubleCheck2.hashCode());


    }
}

3.枚举

Effective Java作者Josh Bloch推荐。

代码语言:javascript
复制
enum Hq
{
    INSTANCE;

    public void printf()
    {
        System.out.println("ins");
    }
}

public class Operation
{
    public static void main(String[] args) {
        Hq hq = Hq.INSTANCE;
        Hq hqq = Hq.INSTANCE;

        System.out.println(hq.hashCode());
        System.out.println(hqq.hashCode());
    }
}

饿汉式的延迟加载问题(可用)

如果创建的对象一定会被使用,那么可以忽略内存浪费的问题。

代码语言:javascript
复制
class SingleTom
{
    private SingleTom()
    { }

    /*
    在静态常量中实例化对象,无法实现延迟加载,如果对象未被使用,会造成内存浪费。(#1)
    无线程安全问题

    将实例化对象放于静态代码块中并无实际作用
     */
    private final static SingleTom instance;  // = new SingleTom();#1

    static  //#2
    {
        instance=new SingleTom();
    }


    public static SingleTom getInstance()
    {
        return instance;
    }
}

public class Operation
{
    public static void main(String[] args) {
        SingleTom hq = SingleTom.getInstance();
        SingleTom hqq = SingleTom.getInstance();

        System.out.println(hq.hashCode());
        System.out.println(hqq.hashCode());
    }
}

懒汉式的线程安全问题(不可用)

代码语言:javascript
复制
class Singletom {

    private static Singletom singleton;

    private Singletom() {}

    /*
    线程不安全:

    调用getInsyance()方法时,如果同时有多个线程同时进入到#1
    就会创建多个实例对象

    倘若在方法上加上syn关键字,线程同步问题解决,但效率大大降低
    
    doublecheck大概就是在这种纠结下选择用两次if(singleton == null)来控制线程同步和效率问题

     */
    public static /*synchronized*/ Singletom getInstance() {
        if (singleton == null) {                   //#1
            singleton = new Singletom();
        }
        return singleton;
    }
}

public class Operation
{
    public static void main(String[] args) {
        Singletom hq = Singletom.getInstance();
        Singletom hqq = Singletom.getInstance();

        System.out.println(hq.hashCode());
        System.out.println(hqq.hashCode());
    }
}

参考文档:

单例模式的八种写法比较

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式定义
  • 推荐使用的三种单例模式
    • 1.DoubleCheck 双重检查
      • 2.静态内部类
        • 3.枚举
          • 饿汉式的延迟加载问题(可用)
            • 懒汉式的线程安全问题(不可用)
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档