文章目录

  • 1、前言
  • 2、怎么区分饿汉和懒汉模式
  • 3、 饿汉
  • 4、懒汉 (双重检查 Double Check Lock)
  • 5、饿汉模式在JDK中的应用(Runtime)
  • 6、相关文章


1、前言

面试时,经常会问到单例模式。

单例模式的两种方式:

  • 饿汉式,就是在类初始化的时候,创建对象。这种方式没有考虑线程安全问题,在多线程下,可能同时存在多个对象。
  • 懒汉式,懒汉式是在第一次使用时才创建对象,在多线程环境中要考虑线程安全问题。

2、怎么区分饿汉和懒汉模式

饿汉: 饿了,饥不择食,系统一运行就创建对象,不考虑太多的问题(如线程安全问题)。

懒汉: 就是懒,就是不想创建对象,即使运行创建对象,每走一步都要找各种理由、说一大堆的问题,要考虑什么多线程、安全,对象重复等问题。总之一句话:懒,就是不想创建。

3、 饿汉

系统一运行就创建对象,不考虑太多的问题,所以可能会被创建多次,存在多个对象。

public class Singleton{
    //类加载时就初始化
    private static final Singleton instance = new Singleton();
    
    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

比较喜欢的方式:饿汉式,不用考虑线程安全问题。

4、懒汉 (双重检查 Double Check Lock)

就是不想创建对象。做什么都要找理由 ( 即使运行创建对象,也要考虑多线程、安全,对象重复等问题)。
总之一句话:懒!

public class Singleton {

	// 必须声明 volatile,在多线程中instance被修改后能立即更新到主内存中
	// 如果不声明,就不是线程安全的
    private volatile static Singleton instance = null; 
    
    private Singleton (){}

    public static Singleton getSingleton() {
        if (instance == null) {                         
            synchronized (Singleton.class) {
                if (instance == null) {       
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }   
}

ReentrantLock 实现 :

import java.util.concurrent.locks.ReentrantLock;

public class Singleton2 {

	// 必须声明 volatile,在多线程中instance被修改后能立即更新到主内存中
	// 如果不声明,就不是线程安全的
	private volatile static Singleton2 instance = null; 

	private static ReentrantLock lock = new ReentrantLock();

	private Singleton2() {
	}

	public static Singleton2 getSingleton() {
		if (instance == null) {
			lock.lock();
			try {
				if (instance == null) {
					instance = new Singleton2();
				}
			} finally {
				lock.unlock();
			}
		}
		return instance;
	}
}

注意:

必须声明 volatile,在多线程中instance被修改后能立即更新到主内存中。

5、饿汉模式在JDK中的应用(Runtime)

java 单例饿汉模式 单例模式懒汉和饿汉java_饿汉