java设计模式之单例模式

设计模式之单例模式

单例模式(Singleton)是设计模式一种,属于建造型的模式。
单例模式,顾名思义就是只有一个实例,该类确保单个对象被创建,可以直接访问,不需要实例化该类的对象,以下是几种创建单例模式的方式

饿汉式

特点
  1. 私有化构造方法
  2. 类加载到内存的时候初始化(类只会加载一次(双亲委派机制),保证实例唯一)
  3. 提供对外获取实例的静态方法
  4. JVM保证线程安全
  5. 比较常用,但容易产生垃圾,因为一开始就初始化
第1种写法
  • 静态对象,类加载时候初始化
public class Singleton1 {
    private static final Singleton1 INSTANCE= new Singleton1();
    
    public static Singleton1 getInstance() {
        return INSTANCE;
    }
    
    private Singleton1() {
    }
}
第2种写法
  • 静态块初始化对象,和第1种一个意思
public class Singleton2 {
    private static final Singleton2 INSTANCE;
    static {
        INSTANCE= new Singleton2();
    }
    
    private Singleton2() {
    }

    public static Singleton2 getInstance() {
        return INSTANCE;
    }
}

懒汉式

特点
  1. 私有化构造方法
  2. 使用的时候才会初始化
  3. 提供对外获取实例的静态方法
第1种写法
  • 使用静态内部类的方式,JVM保证单例,加载外部类时不会加载内部类,这样可以实现懒加载,线程安全
public class Singleton1 {
    private static class Singleton1Holder {
        private static final Singleton1 INSTANCE= new Singleton1();
    }
    
    public static Singleton1 getInstance() {
        return Singleton1Holder.INSTANCE;
    }
    
    private Singleton1() {
    }
}
第2种写法
  • 虽然达到了按需加载的方式,但是线程不安全
public class Singleton2 {
    private static Singleton2 INSTANCE;

    private Singleton2 () {
    }

    public static Singleton2 getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton2 ();
        }
        return INSTANCE;
    }
}
第3种写法
  • 使用synchronized关键字,可以保证线程安全性,但是上来就加锁,锁粒度高,效率低
public class Singleton3 {
    private static Singleton3 INSTANCE;

    private Singleton3() {
    }

    public static synchronized Singleton3 getInstance() {
        if (INSTANCE == null) {
            return new Singleton3();
        }
        return INSTANCE;
    }
}
第4种写法
  • 同样使用synchronized关键字,但做了双重检查(DCL),线程安全,实现延迟初始化,多线程情况下能保持高性能
public class Singleton4 {
    private static volatile Singleton4 INSTANCE; 
    private Mgr06() {
    }

    public static Singleton4 getInstance() {
        if (INSTANCE == null) {
            //双重检查
            synchronized (Singleton4.class) {
                if(INSTANCE == null) {
                    INSTANCE = new Singleton4();
                }
            }
        }
        return INSTANCE;
    }
}
  • 第一次判断INSTANCE == null,为了不必要的加锁,提高性能,如果有一个线程已经创建了,就直接返回该对象
  • 第二次判断INSTANCE == null,为了进行同步,避免多线程问题
  • INSTANCE = new Singleton4()对象的创建在JVM中可能会进行重排序,多线程情况下,创建的对象可能是半初始化状态,使用volatile关键字可以禁止指令重排,解决该问题

枚举模式

特点
  1. 枚举类隐藏了私有的构造器。
  2. 枚举类的域 是相应类型的一个实例对象
  3. 防止反序列化
  4. 线程安全
  5. 《Effective Java》书中推荐的单例模式,日常开发中很少用
写法
public enum Singleton1{
    INSTANCE;
}
  • Disruptor单机最快MQ,使用枚举单例来创建守护线程
package com.lmax.disruptor.util;

import java.util.concurrent.ThreadFactory;

/**
 * Access to a ThreadFactory instance. All threads are created with setDaemon(true).
 */
public enum DaemonThreadFactory implements ThreadFactory
{
    INSTANCE;

    @Override
    public Thread newThread(final Runnable r)
    {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
}

总结

  • 日常开发中 一般采用饿汉式,若对资源十分在意可以采用静态内部类(既保证懒加载又保证安全性),不建议采用懒汉式及双重检测
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值