单例模式

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。(让类自身责任保存它的唯一实例)

单例模式确保对象只有一个,例如数据库连接池或者线程池,只需要一个,不需要new很多,但是要考虑线程安全的问题。

结构图

      

要点:

1.利用static的特性,static的属性和方法是属于类的,它不是靠new出来的,只要类被加载,它就被加载,有且只有一个。

2.构造方法的权限要是private,确保外界不能通过new来获取实例

单例模式又分为饿汉式和懒汉时

1、饿汉式:自己被加载时就将自己实例化。

package com.maggie.singleton;

public class Singleton {
    
    private static  Singleton s = new Singleton();
    //类 一加载s就存在,所以为饿汉式
    
    
    private Singleton() {} //构造函数private,确保外界不能通过new来获取实例
    
    
    public static Singleton getInstance() {
        return s;
    }
}

2、懒汉式:在第一次被引用时,才会将自己实例化

懒汉式面临着多线程访问的安全性问题,需要做双重锁来保证安全

package com.maggie.singleton;

public class Singleton2 {
    private static Singleton2 s = null; 
    //实例一开始为null,类加载时不会也被加载,需要调用getInstance时实例才能被加载

    private Singleton2() {}
    
    public static Singleton2 getInstance() {
        //当多线程进入到这个方法中会导致线程安全问题
        if(s == null) {  
            s = new Singleton2();
        }
        
        return s;
    }
}

                                                                           

双重锁来确保懒汉式线程安全

package com.maggie.singleton;

public class Singleton3 {
    private static Singleton3 instance;

    private Singleton3() {
    }

    public static Singleton3 getSingleton() {

        /*
         * if (instance == null) 为什么两次判断? 
         * 因为如果 同时有两个线程调用getInstance()时,都可以通过第一次instance== null判断
         * 然后进入第二次的instance == null,只能一个线程进入,
         * 其中有一个线程进去了,instance !=null,另一个线程就不用new。
         */

        if (instance == null) {

            synchronized (Singleton.class) { // 不能锁instance,因为一开始instance=null

                if (instance == null) {

                    instance = new Singleton3();

                }

            }

        }

        return instance;

    }

}
原文地址:https://www.cnblogs.com/maggiejyt/p/7443016.html