【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
单例模式作为设计模式中做常见的一种,这里代码也不重复了。
单例模式有9种实现方式,但是其中部分是有缺陷的。总结下来就是四种:
一、饿汉模式
/**
* @ClassName: Singleton2
* @description: 单例模式---饿汉模式(线程安全,但是不节省资源)
* @author: edison_Kwok
* @Date: create in 2019/12/10 22:59
* @Version: 1.0
*/
public class Singleton2 {
private static Singleton2 uniqueSingleton2 = new Singleton2();
private Singleton2() {
}
public static Singleton2 getUniqueSingleton2() {
//线程不安全问题主要是由于 uniqueInstance 被实例化多次,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。
//但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。
return uniqueSingleton2;
}
}
二、双重校验的懒汉模式
/**
* @ClassName: Singleton4
* @description: 单例模式---懒汉模式(双重校验锁-线程安全)
* @author: edison_Kwok
* @Date: create in 2019/12/10 23:09
* @Version: 1.0
*/
public class Singleton4 {
//uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:
//
//为 uniqueInstance 分配内存空间
//初始化 uniqueInstance
//将 uniqueInstance 指向分配的内存地址
//使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
private volatile static Singleton4 uniqueSingleton4;
private Singleton4() {
}
//uniqueInstance 只需要被实例化一次,之后就可以直接使用了。
// 加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。
//双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。
public static Singleton4 getUniqueSingleton4() {
if (uniqueSingleton4 == null) {
synchronized (Singleton4.class) {
if (uniqueSingleton4 == null) {
//如果不加上里面这个null判断,可能就会出现两个线程在次等待
//两个线程都执行new命令
uniqueSingleton4 = new Singleton4();
}
}
}
return uniqueSingleton4;
}
}
三、内部类
/**
* @ClassName: Singleton5
* @description: 静态内部类实现
* @author: edison_Kwok
* @Date: create in 2019/12/10 23:18
* @Version: 1.0
*/
public class Singleton5 {
private Singleton5() {
}
//当 Singleton 类被加载时,静态内部类 SingletonHolder 没有被加载进内存。
private static class Singleton5Holder {
//只有当调用 getUniqueInstance() 方法从而触发 SingletonHolder.INSTANCE 时 SingletonHolder 才会被加载
// 此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。
private static final Singleton5 uniqueSingleton5 = new Singleton5();
}
public static Singleton5 getUniqueSingleton5() {
//这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。
return Singleton5Holder.uniqueSingleton5;
}
}
四、枚举形式(大佬推荐)
/**
* @ClassName: Singleton6
* @description:
* @author: edison_Kwok
* @Date: create in 2019/12/22 20:32
* @Version: 1.0
*/
public enum Singleton6 {
instance;
}
class Client{
public static void main(String[] args) {
Singleton6 instance = Singleton6.instance;
}
}
五、单例模式的注意事项和细节说明
-
- 单例模式保证了系统内存中只存在一个对象,节省了系统内部资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能;
-
- 当想要实例化一个单例类时,必须要记住获取相应获取对象的方法,而不是new;
-
- 单例模式使用场景:需要反复频繁的进行和销毁的对象,创建对象时耗时过多、耗费资源过多(即重量级对象),但又经常用但的对象、工具类对象、频繁范文数据库或者文件的对象(比如数据源、session工厂等)。
六、单例模式在JDK源码
jdk中的java.lang.Runtime类
来源:oschina
链接:https://my.oschina.net/edisonOnCall/blog/3145976