单例模式 创建型模式 提供全局唯一实例
1),私有构造函数 只有自己可以创建
2),唯一的实例,私有静态变量 只有类内部可以调用的类变量
3),静态公开获取对象方法 向外提供唯一的实例
static 关键字 静态方法中只能有静态变量
synchronized 关键字
1,懒汉模式
public class student{
private static Student instance;
private Student(){}
public static Student getInstance(){
if(instance== null){
instance= new Student();
}
return instance;
}
}
2,懒汉模式 线程安全
public class student{
private static Studnet instance;
private Student(){}
public static sychronized Student getInstance(){
if (instance== null){
instance= new Student();
}
return instance;
}
}
3,饿汉模式
public class Student{
private static Student instance= new Student();
private Student(){}
public static Student getInstance(){
return instance;
}
}
4,双重检测 代码块同步检测 防止多线程,线程不安全
第一次检测 检测是否为空
第二次检测 防止多线程进入new 不彻底 例如只分配内存地址,未赋值
public class Student{
private volatile static Student instance;
pirvate Student(){}
public static Student getInstance(){
if(instance == null){
synchronized (Student.class){
if (instance == null){
instance = new Student()
}
}
}
return instance;
}
}
5,静态内部类
public class Student{
private static class StudentHolder {
private static final StudentINSTANCE = new Student();
}
private Student(){}
public static Student getInstance(){
return StudentHolder.studentINSTANCE;
}
}
6,枚举
JDK 版本:JDK1.5 起
是否 Lazy 初始化:否
是否多线程安全:是
实现难度:易
描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
不能通过 reflection attack 来调用私有构造方法。
public emui Student{
INSTANCE;
public void whateverMethod() {
}
}
public class MainClass {
public static void main(String[] args) {
Student s1 = Student.INSTANCE;
Student s2 = Student.INSTANCE;
System.out.println(s1==s2);
}
经验之谈:一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。