单例模式

  1. 什么是单例模式:

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。

  1. 饿汉模式(线程安全)
    类加载时即被创建,整个生命周期都存在,如果该类没有用到会造成内存浪费
public class EHan {
    private static Connection connection = new Connection();
    private EHan() {
    }
    public static Connection getConnection() {
        return connection;
    }
}
  1. 懒汉式-加锁实现
    说到单例模式好多书中都会提到臭名昭著的DCL(double check lock个人理解双重检查加锁),在早起的jvm中同步的开销很大,因此人们想出了一些看似还好的解决方案,如下的两次(connection==null)的判断,人们可以很好的理解独占性却忽略了可见性,new一个对象并设置属性这一部分操作并非原子性的,由于指令重排的原因,其它线程可能取到的可能是一个仅仅部分被构造的Connection对象,比如id是1,name却为null;java5.0以上的版本通过把变量声明为volatile可以启用dcl虽然可以解决这个问题但是已经不推荐这样使用了。
public class ConnectionFactory {
    private static volatile Connection connection;

    private ConnectionFactory() {
    }

    public static Connection getConnection() {
        if (connection == null) {
            synchronized (Connection.class) {
                if (connection == null) {
                    connection = new Connection();
                    connection.setId(1);
                    connection.setName("单例");
                }
            }
        }
        return connection;
    }
}
  1. 静态内部类实现
    推荐使用静态内部类或枚举实现单例模式,枚举实现单例底层其实也可静态内部类实现原理类似
public class Singleton
{
    //静态内部类
    private static class SingletonHolder
    {
        private static final Singleton instance = new Singleton();
    }
    private Singleton(){}
 
    //第一次调用方法时,才会去加载SingleHolder类
    public static final Singleton getInstance()
    {
        return SingletonHolder.instance;
    }
}

  1. 最佳实践枚举实现单例模式

建议使用枚举或者静态内部类实现单例模式,这两种方式及优点(第一种就记缺点)要熟练掌握,初级面试必备
Joshua Bloch的《effective java》中说到:“单元素的枚举类型已经成为实现Singleton的最佳方法”
不废话直接上枚举单例的优点:
1.线程安全
2.避免反射攻击(枚举类继承自抽象类Enum,Enum没有无参构造而且枚举类无法通过反射获取相关method等信息)
3.避免序列化创建对象问题
4.写法简单

public enum ConnectionEnum {
    instance;
    private Connection connection;

    ConnectionEnum() {
        connection = new Connection();
    }

    public Connection getConnection() {
        return connection;
    }
}

6. 枚举单例实战
项目中可能有好多单例实例,怎样统一管理他们呢?定义一个统一的项目用的----单例工厂,隐藏枚举细节,当然把所有单例放到一个类里并不是一个好主意,我们可以分类管理不同的单例,比如把操作数据库(sql和nosql或其他数据存储)的信息放到一起,具体是使用单一原则还是使用分类管理来定义枚举单例工厂类就要看大家的具体业务情况而定了。我们这里演示的是管理所有单例的单例工厂。

public class SingletonFactory {
    private enum DbConnectionEnum {
        factory;
        private Connection connection;
        DbConnectionEnum() {
            //模仿初始化connection的代码
            connection = new Connection();
        }
    }
    
    private enum HbaseConnectionEnum {
        factory;
        private Connection connection;
        HbaseConnectionEnum() {
            connection = new Connection();
        }
    }
    
    private enum EsConnectionEnum {
        factory;
        private Connection connection;
        EsConnectionEnum() {
            connection = new Connection();
        }
    }
    
    public static Connection getDbConnection(){
        return DbConnectionEnum.factory.connection;
    }
    public static Connection getHbaseConnection(){
        return HbaseConnectionEnum.factory.connection;
    }
    public static Connection getEsConnection(){
        return EsConnectionEnum.factory.connection;
    }
}

使用


    public static void main(String[] args) {
        Connection dbConnection = SingletonFactory.getDbConnection();
        Connection hbaseConnection = SingletonFactory.getHbaseConnection();
        Connection esConnection = SingletonFactory.getEsConnection();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值