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

设计模式之单例

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

设计模式之单例

什么是单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、只能有一个实例。
2、必须自己创建自己的唯一实例。
3、必须给所有其他对象提供这一实例。

单例模式特点

1、私有化构造方法
2、在类中创建一个本类对象
3、提供一个全局静态方法获取到该对象

单例模式分类 1、饿汉式

描述: 线程安全,比较常用,但容易产生垃圾,因为一开始就初始化
优点: 没有加锁,执行效率较高
缺点: 类加载时就初始化,浪费内存

例子:

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}
2、懒汉式 ①懒汉式:线程不安全

此方式是最基本的实现,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式,在多线程不能正常工作

例子:

public class Singleton {
    private static Singleton instance;
    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
②懒汉式:线程安全但是效率不高

描述: 这种方式具备很好的延迟加载,能够在多线程中工作,但是效率很低,大多数情况下不需要同步
优点: 第一次调用才初始化,避免内存浪费
缺点: 必须加 synchronized 锁才能保证单例,但加锁会影响效率

例子:

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
③懒汉式:线程安全且高性能

线程安全,延迟初始化,此方式采用双锁机制DCL(double-checked locking),安全且在多线程情况下能保持高性能

例子:

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton() {}
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
    //双重检查模式,进行了两次的判断:
    //第一次是为了避免不要的实例,
    //第二次是为了进行同步,避免多线程问题。
    //由于singleton=new Singleton()对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题
另外2种实现单例模式的方法 ①静态内部类实现单例

这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用
这种方式利用了 classloader 机制来保证初始化 instance 时只有一个线程,它和饿汉式不同的是:饿汉式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),而这种方式是 Singleton 类被装载了,instance 不一定被初始化。只有通过显式调用 getInstance 方法时,才会显式装载 Singleton 类,从而实例化 instance

例子:

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton() {}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
②枚举实现单例

这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化

例子:

public enum Singleton {
    INSTANCE;
    public Singleton getInstance() {
        return INSTANCE;
    }
}

完整的枚举实现单例

public class Person {
    //私有化构造函数
    private Person(){ }

    //定义一个静态枚举类
    static enum SingletonEnum{
        //创建一个枚举对象,该对象天生为单例
        INSTANCE;
        private Person person;
        //私有化枚举的构造函数
        private SingletonEnum(){
            person = new Person();
        }
        public Person getInstnce(){
            return person;
        }
    }

    //对外暴露一个获取User对象的静态方法
    public static Person getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/592500.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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