1.单例设计模式:所谓的单例设计模式,就是在整个软件系统当中,只会产生一个该类的对象。

2.实现方式有两种

2.1饿汉式

public class SingletonTest1 {
	public static void main(String[] args) {
//		Bank bank = new Bank();
		Bank bank1 = Bank.getInstance();
		Bank bank2 = Bank.getInstance();
		// 检查是否相等,如果相等,则说明该类就一个实例
		System.out.println(bank1 == bank2);
	}
}
// 饿汉式实现单例设计模式:在调用之前就已经创建对象了
class Bank{
	//1.私有构造器:意味着外部无法通过构造器去创建对象
	private Bank(){
		
	}
	//2.类的内部去创建这个类的实例
	private static Bank bank = new Bank();
	
	//3.静态方法,返回其bank变量
	public static Bank getInstance(){
		return bank;
	}
}

// 饿汉式的实现方式2
class Dog{
	// 1.私有构造器
	private Dog(){
		
	}
	
	// 2.静态变量接收静态代码块创建的对象
	private static Dog dog = null;
	
	// 3.静态代码块创建对象
	static {
		dog = new Dog();
	}
	
	// 4.静态方法返回dog变量
	public static Dog getInstance(){
		return dog;
	}
}

2.2懒汉式(线程不安全)

package cn.xuguowen.java.singleton;
/*
 *  单例设计模式之懒汉式实现方式:什么时候需要对象我就给你new对象
 */
public class SingletonTest2 {
	public static void main(String[] args) {
		
		Order order1 = Order.getInstance();
		Order order2 = Order.getInstance();
		System.out.println(order1);
		System.out.println(order2);
		System.out.println(order1 == order2);
	}
}

// 懒汉式实现方式
class Order{
	
	//1. 私有构造器
	private Order(){
		
	}
	
	//2.声明属性,但没有初始化
	private static Order order = null;
	
	//3.静态方法返回其对象
	public static Order getInstance(){
		// 这样写方法体是错误的
//		order = new Order();
		// 因为这样每次调用方法就会new一次对象,然后将地址值赋值给order变量
		if(order == null){		
			// 这样判断一下就解决了
			order = new Order();
		}
		return order;
	}
}

2.3解决懒汉式的线程安全问题

package cn.xuguowen.java2;

/**
 * @author xuguowen
 * @create 2021-02-20 9:21
 * @Description     使用同步机制解决懒汉式单例设计模式中的线程安全问题
 *                     有两种方式
 */
public class SingletonTest {

}

class Bank{

    // 私有构造器
    private Bank(){

    }

    // 提供类变量
    private static Bank instance = null;

    // 提供方法,返回一个Bank对象
    // 同步方法解决:效率稍差
    /*public static synchronized Bank getInstance(){

        if (instance == null) {
            // 这样做存在线程安全问题:有可能多个线程都进入到if语句当中,那么就创建了多个实例对象
            // 解决方式一:同步方法
            instance = new Bank();
        }
        return instance;
    }*/

    public static  Bank getInstance(){
        // 方式一:使用同步代码块包裹:效率稍差
        /*synchronized (Bank.class) {
            if (instance == null) {
                // 这样做存在线程安全问题:有可能多个线程都进入到if语句当中,那么就创建了多个实例对象
                instance = new Bank();
            }
            return instance;
        }*/

        // 方式二:效率稍好
        if (instance == null) {
            // 这里虽然也会存在多个线程共同进入if语句,创建了实例之后,即使后面还会有线程进入,此时效率就高了
            synchronized (Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }

            }
        }
        return instance;
    }
}

3.对比两种方式实现单例设计模式

  • 饿汉式:对象加载时间过长,但是线程是安全的
  • 懒汉式:延迟加载对象,线程不安全,需要解决。