第一章 Java 常见设计模式 -《单例模式》
第二章 Java 常见设计模式 -《简单工厂模式》
文章目录
简介
- 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.
- 概念描述
保证一个类仅有且仅有一个实例,并提供一个访问它的全局访问点. - 概念描述
1、单例类有且只有一个实例。 2、单例类必须只能自己创建自己的唯一实例 (构造函数私有)。 3、单例类必须能给所有其他对象提供这一实例(提供获取实例的方法)。
- 场景 :当您想控制实例数目,节省系统资源的时候。
- 目的 : 解决一个全局使用的类频繁地创建与销毁.
一、实现方式?
1. 懒汉式(延迟加载)
- (一). 线程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- (二). synchronized 方法 - 线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- (三). synchronized 代码块 - 线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
// 使用synchronized 块,临界资源的同步互斥访问
synchronized(Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
}
- (四). 双重检测 - 线程安全
public class Singleton {
//使用volatile关键字防止重排序,因为 new Instance()是一个非原子操作,可能创建一个不完整的实例
private static volatile Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class){ // 使用synchronized 块,临界资源的同步互斥访问
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
- (五). 内部类实现 - 线程安全
// 线程安全的懒汉式单例
public class Singleton {
// 私有内部类,按需加载,用时加载,也就是延迟加载
private static class Holder {
private static Singleton singleton = new Singleton();
}
private Singleton() {
}
public static Singleton getSingleton() {
return Holder.singleton;
}
volatile:
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
- (六). ThreadLocal - 线程安全
public class Singleton {
// ThreadLocal 线程局部变量,将单例instance线程私有化
private static ThreadLocal<Singleton> threadlocal = new ThreadLocal<Singleton>();
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
// 第一次检查:若线程第一次访问,则进入if语句块;否则,若线程已经访问过,则直接返回ThreadLocal中的值
if (threadlocal.get() == null) {
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查:该单例是否被创建
instance = new Singleton();
}
}
threadlocal.set(instance); // 将单例放入ThreadLocal中
}
return threadlocal.get();
}
}
2. 饿汉式(立即加载)
- 线程安全
优点: 没有加锁,执行效率会提高;public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
缺点:类加载时就初始化,浪费内存。