单例模式 Singleton Pattern笔记

单例模式 Singleton Pattern

单例模式(Singleton Pattern)属于创建型模式,它提供了一种创建单一对象的方式。
单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。
通常,我们在new一个对象时,不能防止它被实例化多次,怎样保证它只被实例化一次呢,一个最好的办法就是让这个类自身去创建并保存它的唯一实例,再提供一个访问该实例的公共方法,那么就能保证它被实例化一次了。

一、单例模式的实现方式

在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。
Singleton也能够被无状态化。提供工具性质的功能。

1.懒汉式(延迟加载)

在被引用时才会实例化自己

public class Singleton1 {
    private static Singleton1 instance;
    //构造方法私有化,防止外界利用new创建此实例的可能
    private Singleton1(){

    }

    public static Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }
        return instance;
    }
}

2.饿汉式(贪懒加载)

public class Singleton {
    private static Singleton singleton= new Singleton();

    private singleton() {
    }

    public static Singleton newInstance() {
        return singleton;
    }
}

饿汉式示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个singleton对象

优化后??????????????????

public class Singleton3 {
    // 私有构造
    private Singleton3() {}

    private static Singleton3 single = null;

    public static Singleton3 getInstance() {

        // 等同于 synchronized public static Singleton3 getInstance()
        synchronized(Singleton3.class){
          // 注意:里面的判断是一定要加的,否则出现线程安全问题
            if(single == null){
                single = new Singleton3();
            }
        }
        return single;
    }
}

3.双重检查加锁

这个是懒汉形式的加强版,将synchronized关键字移到了newInstance方法里面,同时将singleton对象加上volatile关键字,这种方式既可以避免多线程问题,又不会降低程序的性能。但volatile关键字也有一些性能问题,不建议大量使用。

使用双重检查进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。

public class Singleton4 {
    // 私有构造
    private Singleton4() {}

    private static Singleton4 single = null;

    // 双重检查
    public static Singleton4 getInstance() {
        if (single == null) {
            synchronized (Singleton4.class) {
                if (single == null) {
                    single = new Singleton4();
                }
            }
        }
        return single;
    }
}

4.Lazy initialization holder class

这里创建了一个内部静态类,通过内部类的机制使得单例对象可以延迟加载,同时内部类相当于是外部类的静态部分,所以可以通过jvm来保证其线程安全。这种形式比较推荐。

public class Singleton4 {
    // 私有构造
    private Singleton4() {}

    private static Singleton4 single = null;

    // 双重检查
    public static Singleton4 getInstance() {
        if (single == null) {
            synchronized (Singleton4.class) {
                if (single == null) {
                    single = new Singleton4();
                }
            }
        }
        return single;
    }
}

5.枚举

public enum Singleton {
    singleton
}
public class SingletonFactory {
    
    // 内部枚举类
    private enum EnmuSingleton{
        Singleton;
        private Singleton8 singleton;
        
        //枚举类的构造方法在类加载是被实例化 
        private EnmuSingleton(){
            singleton = new Singleton8();
        }
        public Singleton8 getInstance(){
            return singleton;
        }
    }
    public static Singleton8 getInstance() {
        return EnmuSingleton.Singleton.getInstance();
    }
}

class Singleton8{
    public Singleton8(){}
}

使用注意

使用Singleton注意事项:

有时在某些情况下,使用Singleton并不能达到Singleton的目的,如有多个Singleton对象同时被不同的类装入器装载;在EJB这样的分布式系统中使用也要注意这种情况,因为EJB是跨服务器,跨JVM的。

Singleton模式看起来简单,使用方法也很方便,但是真正用好,是非常不容易,需要对Java的类 线程 内存等概念有相当的了解。

引用

Java设计模式之单例模式详解
单例模式的5种形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值