单例模式

单例模式

八种创建方式

1、饿汉式

优点:

  • 简单好理解,便于使用,推荐实际工作中使用
  • 线程安全

缺点

  • 不能实现lazy-loading(懒加载),
    即不管用到与否,类装载时即完成初始化。

  • 实现机制:将构造器私有化 即外部不可以调用构造方法构造新对象

  • 所有获取该类对象的操作 只能通过getInstance方法来进行获取。

public class Singleton01HungryDemo {

    private static final Singleton01HungryDemo instance = new Singleton01HungryDemo();

    /**
     * 构造方法私有化
     */
    private Singleton01HungryDemo() {
    }

    /**
     * 给外部提供获取实例的方法
     * @return
     */
    public static Singleton01HungryDemo getInstance() {
        return instance;
    }
}

2、静态代码块饿汉式

3、懒汉式

优点:

  • 只有真正用到时候才进行加载

缺点:

  • 线程不安全(不推荐使用,没有实用价值)
  • 线程不安全的详解:如果多个线程同时进行到代码的21行即进行判断是否为null,同时均为null,即会执行实例化的代码无法保证单例,提供了简单的验证办法,即启动100个线程同时进行调用,判断hashcode是否相同
public class Singleton02LazyDemo01 {
    private static Singleton02LazyDemo01 instance;

    private Singleton02LazyDemo01() {
    }

    public static Singleton02LazyDemo01 getInstance() {
        if (null == instance) {
            //线程进行短暂休眠,不然很难看到效果
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new Singleton02LazyDemo01();
        }
        return instance;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() ->
                    System.out.println(Singleton02LazyDemo01.getInstance().hashCode())
            ).start();
        }
    }

}

4、加锁类型的懒汉式(sychornized锁方法实现)

优点:

  • 在原有基础上保证了线程安全

缺点:

  • 每次都要获取锁释放锁 效率低下(不推荐使用)
public class Singleton03LazyDemo02 {

    private Singleton03LazyDemo02() {
    }
    private static Singleton03LazyDemo02 instance;

    public static synchronized Singleton03LazyDemo02 getInstance(){
        if(null == instance){
            //线程进行短暂休眠,不然很难看到效果
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new Singleton03LazyDemo02();
        }
        return instance;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() ->
                    System.out.println(Singleton03LazyDemo02.getInstance().hashCode())
            ).start();
        }
    }
}

5、加锁代码块形式的懒汉式

  • 试图通过加同步代码块来进行效率提升,但仍然线程不安全当判断等于null之后,虽然获取不到锁,但是,当获取到锁之后依然会执行new的操作,即不再是单例的

优点:

  • 没有

缺点:

  • 线程并不安全
public class Singleton04LazyDemo03 {
    private Singleton04LazyDemo03() {
    }

    private static Singleton04LazyDemo03 instance;

    public static Singleton04LazyDemo03 getInstance() {
        if (null == instance){
            synchronized (Singleton04LazyDemo03.class){
                instance = new Singleton04LazyDemo03();
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() ->
                    System.out.println(Singleton04LazyDemo03.getInstance().hashCode())
            ).start();
        }
    }
}

6、双重检查机制的懒汉式

  • 通过两次检测保证了线程安全,而且效率
    相比直接加锁的形式效率要高很多,推荐
    使用
public class Singleton05LazyDemo04DoubleCheck {
    private Singleton05LazyDemo04DoubleCheck() {
    }
    //防止指令重排
    private static volatile Singleton05LazyDemo04DoubleCheck instance;

    public static Singleton05LazyDemo04DoubleCheck getInstance() {
        if (null == instance) {
            synchronized (Singleton05LazyDemo04DoubleCheck.class) {
                if (null == instance) {
                    instance = new Singleton05LazyDemo04DoubleCheck();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() ->
                    System.out.println(Singleton05LazyDemo04DoubleCheck.getInstance().hashCode())
            ).start();
        }
    }
}

7、静态内部类形式的实现

通过静态内部类的形式来实现单例

优点:

  • 线程安全,实现了lazy-loading 推荐使用
public class Singleton06InnerClass {
    private Singleton06InnerClass() {
    }

    private static class InnerClass {
        private static final Singleton06InnerClass instance = new Singleton06InnerClass();
    }

    public static Singleton06InnerClass getInstance() {
        return InnerClass.instance;
    }
}

8、enum形式的实现

  • 完美写法 不仅可以解决线程同步,还可以防止反序列化即可以防止暴力反射
public enum Singleton07Enum {

    INSTANCE;

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() ->
                    System.out.println(Singleton07Enum.INSTANCE.hashCode())
            ).start();
        }
    }
}

总结 其实真正意义上最简单实用的就是第一种饿汉式,不能懒加载,影响并不很大

代码下载链接地址:

我的gitee

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值