单例(Singleton)模式 也叫单态模式,是java的23种设计模式之一。单例模式的实现有两种方式:懒汉式,饿汉式。

一:应用场景

1.整个程序的运行中只允许有一个类的实例;

2.需要频繁实例化然后销毁的对象。

3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

4.方便资源相互通信的环境

二、单例模式的具体使用

1.封装一些常用的工具类,保证整个应用常用的数据统一

2.保存一些共享数据在内存中,其他类随时可以读取。

三、单例模式实现步骤

1.构造方法必须进行私有化

2.实例必须是一个且唯一,并且必须加上static属性

3.对外提供获取该类对象的共有方法也是static属性

四、代码说明

1:饿汉式————类在加载时,直接加载到内存后,就实例化一个单例,JVM保证线程安全

     * 简单实用,推荐使用!

     * 唯一缺点:不管用到与否,类装载时就完成实例化

//第一种方式
public class TestSingleton {
    private static final TestSingleton test = new TestSingleton();
    private TestSingleton () {};//单例模式特点,构造方法必须私有化

    public static TestSingleton getInstance() {
        return test;
    }
}
//第二种方式
public class TestSingleton {
    private static final TestSingleton test ;
    static {
        test = new TestSingleton();
    }
    private TestSingleton () {};
    public static TestSingleton getInstance() {
        return testSingleton ;
    }
}

2:懒汉式————懒汉式就是不在系统加载时就创建类的单例,而是在第一次使用实例的时候再创建。也就是需要时才创建于堆中,多线程情况下不能保证唯一性

public class TestSingleton {
    private static TestSingleton test ;
    private TestSingleton () {};
    public static TestSingleton getInstance() {
        if(test ==  null){
            test = new TestSingleton();
        }
        return test;
    }
}

※※※※※多线程情况下,建议使用饿汉式的单例模式。但是并不意味着不能使用懒汉式。可以使用双重检验(也就是给线程加锁,并双重检验是否已创建实例)来实现懒汉式单例模式。如下:

public class Test{
    private static volatile Test test; 

    private Test() {
    }
    //不使用synchronized锁代码块,因为锁住代码块 每一次执行时都要进行同步和判断,无疑会拖慢速度
    //同时带来线程不安全的问题并且效率下降
    public static Test getInstance() {
        if (test == null) {
            //双重检查
            synchronized (Test.class) {
                if(test == null) {
                    test = new Test();
                }
            }
        }
        return test;
    }
}

※※※※※静态内部类的方式也可以实现懒加载,并且不需要使用synchronized来保证线程安全,它的线程安全是通过JVM来实现的,JVM在加载类的时候不会加载内部类,只有调用的是很好  才会加载——能实现延时加载和线程安全

public class Test {

    private Test() {
    }

    private static class TestHolder {
        private final static Test testCase = new Test();
    }

    public static Mgr07 getInstance() {
        return Test.testCase;
    }
}