【面试】单例的实现方式

55 篇文章 2 订阅
16 篇文章 0 订阅

一.说明

1.属于创建者模式
2.Singleton Pattern
3.设计到一个单一的类,负责创建自己的对象,确保只有单个对象被创建
4.提供一种访问唯一对象的方式
5.实现思路
	a.私有化构造方法
	b.创建对象
	c.提供公共方法获取对象

二.实现分类

1.饿汉式:类加载就创建类单例对象
2.懒汉式:类加载不创建单例对象,首次使用才创建

三.饿汉式实现

1.静态变量
package com.learning.singleton;

/**
 * @Description 静态变量实现单例
 */
public class Static_Variable_Singleton {
    // 1.私有化构造函数
    private Static_Variable_Singleton(){}
    // 2.静态变量,类加载就创建
    private static Static_Variable_Singleton singleton = new Static_Variable_Singleton();
    // 3.提供获取单例的静态方法,static修饰,否则需要对象调用
    public static Static_Variable_Singleton getInstance(){
        return singleton;
    }

    public static void main(String[] args) {
        Static_Variable_Singleton instance1 = Static_Variable_Singleton.getInstance();
        Static_Variable_Singleton instance2 = Static_Variable_Singleton.getInstance();
        System.out.println(instance1 == instance2);
    }
}
2.静态代码块
package com.learning.singleton;

/**
 * @Description 静态代码块单例
 */
public class Static_Block_Singleton {
    /**
     * 1.不是static修饰,静态代码块无法赋值
     * 2.不是private修改,外界可通过Static_Block_Singleton.singleton获取
     * 3.singleton变量只能静态代码块外部声明,否则公有方法无法返回
     */
    private static Static_Block_Singleton singleton;
    // 1.私有化构造方法
    private Static_Block_Singleton(){}
    // 2.静态代码块创建对象
    static {
        singleton = new Static_Block_Singleton();
    }
    // 3.提供公有方法获取单例对象
    public static Static_Block_Singleton getInstance(){
        return singleton;
    }

    public static void main(String[] args) {
        Static_Block_Singleton instance1 = Static_Block_Singleton.getInstance();
        Static_Block_Singleton instance2 = Static_Block_Singleton.getInstance();
        System.out.println(instance1 == instance2);
    }
}
3.枚举方式
  • 枚举类实现单例模式是极力推荐的单例实现模式,因为枚举类型是线程安全的,只会装载一次,设计者充分利用了枚举的这个特性来实现单例模式,枚举类型是所用单例实现中唯一一种不会被破坏的单例实现模式。
package com.learning.singleton;

/**
 * 枚举方式
 */
public enum Enum_Singleton {
    INSTANCE;

    public static void main(String[] args) {
        Enum_Singleton instance1 = Enum_Singleton.INSTANCE;
        Enum_Singleton instance2 = Enum_Singleton.INSTANCE;
        System.out.println(instance1 == instance2);
    }
}

四.懒汉式实现

1.线程不安全的懒汉式
package com.learning.singleton;

/**
 * @Description 线程不安全的懒汉式单例
 */
public class Lazy_Singleton_Not_Safe {
    // 1.私有化构造函数
    private Lazy_Singleton_Not_Safe(){}
    // 2.静态变量
    private static Lazy_Singleton_Not_Safe singleton;
    // 3.提供获取单例的静态方法,多线程下会有问题
    public static Lazy_Singleton_Not_Safe getInstance(){
        if(singleton == null){
            singleton = new Lazy_Singleton_Not_Safe();
        }
        return singleton;
    }

    public static void main(String[] args) throws InterruptedException {
        Lazy_Singleton_Not_Safe instance1 = Lazy_Singleton_Not_Safe.getInstance();
        Lazy_Singleton_Not_Safe instance2 = Lazy_Singleton_Not_Safe.getInstance();
        System.out.println(instance1 == instance2);
    }
}
2.线程安全的懒汉式
package com.learning.singleton;

/**
 * @Description 线程安全的懒汉式单例
 */
public class Lazy_Singleton_Safe {
    // 1.私有化构造函数
    private Lazy_Singleton_Safe(){}
    // 2.静态变量
    private static Lazy_Singleton_Safe singleton;
    // 3.提供获取单例的静态方法,加了synchronized同步锁,但效率不高
    public static synchronized Lazy_Singleton_Safe getInstance(){
        if(singleton == null){
            singleton = new Lazy_Singleton_Safe();
        }
        return singleton;
    }

    public static void main(String[] args) throws InterruptedException {
        Lazy_Singleton_Safe instance1 = Lazy_Singleton_Safe.getInstance();
        Lazy_Singleton_Safe instance2 = Lazy_Singleton_Safe.getInstance();
        System.out.println(instance1 == instance2);
    }
}

3.线程安全效率高的懒汉式(双重检查锁)
package com.learning.singleton;

/**
 * @Description 线程安全、性能高的懒汉式单例
 */
public class Lazy_Singleton_Double_Check_Lock {
    // 1.私有化构造函数
    private Lazy_Singleton_Double_Check_Lock(){}
    // 2.静态变量
    // 多线程下 jvm在实例化对象的时候会进行优化和指令重排序操作,需要使用volatile保证可见性和有序性
    private static volatile Lazy_Singleton_Double_Check_Lock singleton;
    // 3.提供获取单例的静态方法,加了synchronized同步锁,但效率不高
    public static Lazy_Singleton_Double_Check_Lock getInstance(){
        if(singleton == null){
            synchronized (Lazy_Singleton_Double_Check_Lock.class){
                if(singleton == null){
                    singleton = new Lazy_Singleton_Double_Check_Lock();
                }
            }
        }
        return singleton;
    }

    public static void main(String[] args) throws InterruptedException {
        Lazy_Singleton_Double_Check_Lock instance1 = Lazy_Singleton_Double_Check_Lock.getInstance();
        Lazy_Singleton_Double_Check_Lock instance2 = Lazy_Singleton_Double_Check_Lock.getInstance();
        System.out.println(instance1 == instance2);
    }
}

4.静态内部类
  • jvm在加载外部类的过程中,是不会加载静态内部类的,只有内部类的属性/方法被调用时才会被加载,并初始化其静态属性。静态属性被static修饰,保证只被实例化一次,严格保证实例化顺序
  • 静态内部类单例模式是开源项目常见的一种单例模式。在没有加任何锁的情况下,保证了多线程下的安全,没有任何性能影响和空间的浪费。
package com.learning.singleton;
/**
 * @Author wangyouhui
 * @Description 静态内部类懒汉式单例
 **/
public class Lazy_Static_Inner_Class {
    // 1.私有构造方法
    private Lazy_Static_Inner_Class(){}
    // 2.定义一个静态内部类
    private static class Static_Inner_Class{
        // 在内部类中声明并初始化外部类对象
        private static Lazy_Static_Inner_Class instance = new Lazy_Static_Inner_Class();
    }

    // 3.提供公共的访问方式
    public static Lazy_Static_Inner_Class getInstance(){
        return Static_Inner_Class.instance;
    }

    public static void main(String[] args) {
        Lazy_Static_Inner_Class instance1 = Lazy_Static_Inner_Class.getInstance();
        Lazy_Static_Inner_Class instance2 = Lazy_Static_Inner_Class.getInstance();
        System.out.println(instance1 == instance2);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王佑辉

老板,赏点吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值