Java单例模式

单例模式

1)概念:

一种常用的软件设计模式。所谓单例,就是让一个类在项目运行中只存在一个对象,即使用到这个类的地方很多,也只存在一个对象。

2) 好处:

1,节省内存

2,有些情况下不用单例模式可能会引起代码逻辑错误(例如:网站访问量统计功能ServletContext (servlet) Application(jsp)) application.setAttrbute("count",100);

3) 单例模式要点

1. 是单例模式的类只提供私有的构造函数

2. 是类定义中含有一个该类的静态私有对象;

3. 是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。

实现方式(7种):

饿汉(starving):该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。特点是加载类的时候比较慢,但运行时获得对象的速度比较快。从加载到应用结束会一直占用资源。

1),饿汉线程安全

//饿汉式单例模式
public class Hungry1{

    //可能会浪费空间
    private byte[] data1 = new byte[1024*1024];
    private byte[] data2 = new byte[1024*1024];
    private byte[] data3 = new byte[1024*1024];
    private byte[] data4 = new byte[1024*1024];
//1.私有的构造方法 防止在其他地方创建对象
    private Hungry1(){}
//2.静态私有的类实例static伴随着类的加载而执行,并且只执行一次 私有防止该属性在其他类中被访问
    private static final Hungry1 instance = new Hungry1();
//3, 公共静态的方法,返回该类的实例
    private static Hungry1 getInstance(){
        return instance;
    }

}

2),饿汉静态线程安全

public class Hungry2{
    //可能会浪费空间
    private byte[] data1 = new byte[1024*1024];
    private byte[] data2 = new byte[1024*1024];
    private byte[] data3 = new byte[1024*1024];
    private byte[] data4 = new byte[1024*1024];

    private Hungry2(){}

    private static final Hungry2 instance;

    static {
        instance = new Hungry2();
    }

    private static Hungry2 getInstance(){
        return instance;
    }
}

懒汉(slacker):该单例类非常懒,只有在自身需要的时候才会行动,从来不知道及早做好准备。特点是运行时获得对象的速度比较慢,但加载类的时候比较快。整个应用的生命周期只有一部分时间在占用资源。

3),懒汉线不安全:

//懒汉式单例模式
public class LazyMan1{
//1.私有的构造方法 防止在其他地方创建对象
    private LazyMan1(){}
//2.静态私有的类实例static伴随着类的加载而执行,并且只执行一次 私有防止该属性在其他类中被访问
    private static LazyMan1 instance;
//3, 公共静态的方法,返回该类的实例
    private static LazyMan1 getInstance(){

        if (instance==null){
            instance = new LazyMan1();
        }
        return instance;
    }
}

4),懒汉线程安全

//懒汉式单例模式
public class LazyMan2 {
    private LazyMan(){}
    private static LazyMan2 instance;

    private static synchronized LazyMan2 getInstance(){

        if (instance==null){
            instance = new LazyMan2();
        }
        return instance;
    }

}

5)懒汉线程安全双重加锁(双检索)

//双检索式单例模式
public class LazyManDoubleLock {

    private LazyManDoubleLock(){}

    /**
     * 1.分配内存空间
     * 2.执行构造方法,初始化对象
     * 3.把这个对象指向这个空间
     *
     * 我们期望的操作顺序是123
     * 但是,因指令重排它有可能执行132
     * 如,执行132是线程A 没有问题,但是此时有一个线程B,
     * 它就会判断instance是不等于null,所有会直接return instance
     * 直接return的话还没有走构造方法,没有进行初始化
     * 所有变量前要用volatile进行修饰
     * volatile 关键字作用为禁止指令重排,保证返回
     */
    private static volatile LazyManDoubleLock instance;

    //双重检测锁模式的 懒汉式单例  DCL懒汉式
    private static LazyManDoubleLock getInstance(){
    //判断,当instance等于null的时候也就是需要的时候才进行初始化
        if(instance==null){
            synchronized (LazyManDoubleLock.class){
                if (instance==null) {
                    instance = new LazyManDoubleLock();//不是原子性操作
                }
            }
        }
        return instance;
    }
}

6), 枚举单例模式

//枚举单例模式
public enum  EnumSingleton {
    Enum_Singleton;
    public void doAnything(){
        System.out.println("doAnything");
    }
}

7), 静态内部类

静态内部类 (实例消耗资源时,实现延迟加载)外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。

//静态内部类
public class StaticInternal {

    private StaticInternal(){}

    public static StaticInternal getInstance(){
        return InnerClass.STATIC_INTERNAL;
    }

    public static class InnerClass{
        private static final StaticInternal STATIC_INTERNAL = new StaticInternal();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值