栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式之单例模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式之单例模式

单例模式 定义

在整个程序中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象的方法。

饿汉式(静态常量)

构造器私有化,无法通过new创建对象,在类的内部完成对象的创建,对外提供一个静态方法,返回该对象的实例。

public class HungryStaticConstant {

    //构造器私有化,无法通过new创建对象,
    private HungryStaticConstant(){}

    private final static HungryStaticConstant hungryStaticConstant = new HungryStaticConstant();

    //对外提供一个静态方法,返回该对象的实例
    public static HungryStaticConstant getInstance(){
        return hungryStaticConstant;
    }
}

优点: 写法简单,类装载的时候完成了实例化,避免了线程同步的问题。
缺点: 没有完成懒加载的效果,如果没有用到这个实例会造成资源浪费。

饿汉式(静态代码块)

与静态常量类似

public class HungryStaticCodeBlock {
    //构造器私有化,无法通过new创建对象,
    private HungryStaticCodeBlock(){}

    private static HungryStaticCodeBlock hungryStaticCodeBlock;

    //静态代码块,返回实例对象
    static{
        hungryStaticCodeBlock = new HungryStaticCodeBlock();
    }

    //对外的静态方法,返回对象的实例
    public static HungryStaticCodeBlock getInstance(){
        return hungryStaticCodeBlock;
    }
}

优点缺点同饿汉式(静态常量)

懒汉式(线程不安全)
public class LazyNonSafeThread {

    private static LazyNonSafeThread lazyNonSafeThread;

    //构造函数私有化
    private LazyNonSafeThread(){}

    //提供一个静态方法,当使用该方法时才创建实例
    public static LazyNonSafeThread lazyNonSafeThread(){
        if(lazyNonSafeThread == null){
            //没创建时,创建实例
            lazyNonSafeThread = new LazyNonSafeThread();
        }
        return lazyNonSafeThread;
    }
}

优点: 起到了懒加载的效果,但是只能在单线程下使用。
缺点: 如果多线程的情况下,多个线程都进入到了if判断的情况中就会产生多个实例,就不是单例模式了。

懒汉式(线程安全)
public class LazySafeThread {

    private static LazySafeThread lazySafeThread;

    //构造函数私有化
    private LazySafeThread(){}

    //提供一个静态方法,当使用该方法时才创建实例
    public static synchronized LazySafeThread lazySafeThread(){
        if(lazySafeThread == null){
            //没创建时,创建实例
            lazySafeThread = new LazySafeThread();
        }
        return lazySafeThread;
    }
}

问题: 效率太低,获取线程实例的时候每次都要进行同步。

双重检查实现单例模式
public class DoubleCheck {
    
    //增加volatile关键字
    private static volatile DoubleCheck doubleCheck;

    private DoubleCheck(){}

    public static DoubleCheck doubleCheck(){
        //第一层检查
        if(doubleCheck == null){
            synchronized (DoubleCheck.class){
                //第二层检查
                if(doubleCheck == null){
                    doubleCheck = new DoubleCheck();
                }
            }
        }
        return doubleCheck;
    }
}

解决了线程安全问题,同时也解决了懒加载问题。
实际开发中推荐使用这种单例设计模式。

静态内部类
public class StaticInnerClass {

    private StaticInnerClass(){}

    //类装载的时候静态内部类不会装载
    private static class InnerClass{
        private final static StaticInnerClass staticInnerClass = new StaticInnerClass();
    }

    public static StaticInnerClass getInstance(){
        return InnerClass.staticInnerClass;
    }

}

当调用getInstance时才会装载内部类,装载时是线程安全的,所以此方法也是线程安全的并且兼顾懒加载的特性。

此外还可以同步借助枚举来实现单例模式,不仅能避免多线程的同步问题,而且还能通过反序列化重新创建对象,也是《EFFECTIVE JAVA》的作者Josh Bloch提倡的方式
在Java中Runtime就是经典的单例模式:

使用场景: 需要频繁创建和销毁对象,重量级对象(创建对象耗时过多或消耗资源过多),经常用到的对象、工具类对象等。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/276320.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号