系统中只有一个该类的一个对象实例
redis
连接对象Spring IOC
容器中的默认beanSpringBoot
中的controller
、service
、dao
层通过Autowire
的依赖注入对象默认都是单例的。用途:懒加载、延时加载,延迟创建对象
实现方式:
详细代码
package com.example.test.single;
/**
* @author 晓果冻
* @version 1.0
* @date 2021/10/21 21:47
*/
public class SingletonLazy {
public static SingletonLazy instance;
/**
* 构造函数私有化,外界不能通过new创建该对象
*/
private SingletonLazy() {
}
/**
* 对外只提供一个创建实例的方法,多线程下不安全
*
* @return
*/
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
/**
* 通过synchronized枷锁保证多线程下的单例
* 但synchronized开销大,又是在方法级别上控制的
*
* @return
*/
public static synchronized SingletonLazy getInstance02() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
/**
* 这是否安全,instance = new SingletonLazy(); 并不是原子性操作
* 1、分配空间给对象
* 2、在空间内创建对象
* 3、将对象赋值给引用instance
*
* 假如线程 1-》3-》2顺序,会把值写会主内存,其他线程就会读取到instance最新的值,但是这个是不完全的对象
* (指令重排)
* @return
*/
public static SingletonLazy getInstance03() {
if (instance == null) {
//假设此时同时有A、B线程满足到达这里
synchronized (SingletonLazy.class) {
//加锁 控制只有一个线程占有此锁
if (instance == null) {
//涉及双重锁检查,如果现在堆中分配了空间,堆是线程共享的,所以其他线程都可以读到此空间内容
instance = new SingletonLazy();
}
}
}
return instance;
}
/**
* volatile是Java提供的关键字,它具有可见性和有序性,
* 指令重排序是JVM对语句执行的优化,只要语句间没有依赖,那JVM就有权对语句进行优化
* 禁止了指令重排
*/
private static volatile SingletonLazy volatileInstance01;
public static SingletonLazy getInstance04() {
//第一重检查
if (volatileInstance01 == null) {
// A、B ,锁定
synchronized (SingletonLazy.class) {
//第二重检查
if (volatileInstance01 == null) {
volatileInstance01 = new SingletonLazy();
}
}
}
return volatileInstance01;
}
}
用途:因为饿,所以急切需要对象。提前创建对象
实现方式:
详细代码
package com.example.test.single;
/**
* @author cgd
* @date 2021/10/27 17:54
*/
public class SingletonHungry {
private static SingletonHungry instance = new SingletonHungry();
private SingletonHungry() {
}
public static SingletonHungry getInstance() {
return instance;
}
}
JDK
源码中的单例设计模式