定义
确保一个类只有一个实例,并提供一个全局访问点。
/**
* “双重检查加锁”
* Author: zyfu
* Date: 2020/1/20 14:37
*/
public class Singleton {
/*
volatile 确保:当instance 变量被初始化时,多个线程正确的处理变量。
Volatile可以看做是轻量级的 Synchronized,它只保证了共享变量的可见性。
在线程 A 修改被 volatile 修饰的共享变量之后,线程 B 能够读取到正确的值。
java 在多线程中操作共享变量的过程中,会存在指令重排序与共享变量工作内存缓存的问题。
*/
private volatile static Singleton instance;
//构造方法私有化
private Singleton(){}
//静态方法获取实例对象
public static Singleton getInstance(){
//双重检查加锁
if (instance == null) {
synchronized (Singleton.class) {
//第一次才会执行synchronized中的代码
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
以上是单例模式的懒汉式,当第一次调用getInstance()方法时才会创建Singleton对象。
/**
* 饿汉式创建实例
* Author: zyfu
* Date: 2020/1/20 14:34
*/
public class Singleton2 {
/**
* 急切创建实例,jvm在加载类时创建实例,
* 访问getInstance()方法之前,一定会先创建实例
*/
private static Singleton2 instance = new Singleton2();
private Singleton2(){}
public static Singleton2 getInstance() {
return instance;
}
}
以上是饿汉式创建实例,当类被加载时创建实例。
单例模式特点
- 私有化构造器
- 提供一个全局访问点(公开的静态方法用于获取实例对象)
类加载器对单例模式的影响?
多个类加载器会各自创建自己的单例对象。每个类加载器有定义了一个命名空间,不同的类加载器可能会加载同一个类,从整个程序来看,同一个类被加载多次,从而产生多个单例实例对象。所以,当程序中有多个类加载器有同时使用了单例模式,需要注意!!解决办法:自行指定类加载器,并指定同一个类加载器。
总结
- OO原则
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
- 为交互对象之间的松耦合设计而努力
- 类应该对扩展开放,对修改关闭
- 依赖抽象,不要依赖具体类
- 要点
- 单例模式确保程序中一个类最多只有一个实例。
- 单例模式也要提供访问这个实例的全局点。
- 在java中实现单例模式需要私有化构造器、一个静态方法和一个静态变量
- 确保在性能和资源上的限制,然后小心的选择适当的方案来实现单例模式,已解决多线程的问题(一般认为所有的程序都是多线程的)。
- 如果使用多个类加载器,可能导致单例模式失效而产生多个实例对象。
- java 1.2及以前的版本必须建立单例注册表,避免GC回收单例(现在还有用这么低版本的吗????)