题目:设计一个类,我们只能生成该类的一个实例。
要点:既然只生成一个实例,那么必须私有化构造函数
实现的方式有哪些:
- 饿汉式(线程安全,无法实现懒加载,浪费资源)
- 懒汉式(方法需要加synchronized才能实现线程安全,但这样效率就不如饿汉式了,懒汉式能实现懒加载)
- 双重锁判定机制(不建议使用,由于JAVA是实行无序写入的机制,有可能产生错误)
- 静态内部类实现(线程安全,可以延时加载)
- 枚举类实现(线程安全,不能延时加载)
饿汉模
代码语言:javascript复制public class Singleton1 {
private static Singleton1 instance = new Singleton1();
// 私有化构造函数
private Singleton1() {}
public static Singleton1 getInstance() {
return instance;
}
}
懒汉式
代码语言:javascript复制public class Singleton2 {
// 这里可以延时加载,用的时候再创建对象
private Singleton2 instance;
// 私有化构造方法
private Singleton2() {}
public static synchronized Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
双重锁判定机制
代码语言:javascript复制public class Singleton3 {
private static Singleton3 instance;
// 私有化构造方法
private Singleton3() {}
public static Singleton3 getInstance() {
if (instance == null) {// 1
synchronized (Singleton3.class) {
if (instance == null) {// 2
instance = new Singleton3(); // 3
}
}
}
return instance;
}
}
/*1和2俩处进行了判定,也就是进行了俩次判定,文章开头说不推荐使用这
种方式,是因为java实行无序写入的机制,在3处的代码处运行过程中,
instance对象还没构造完时,这是有现车访问代码1处,且判断instance
不为空,然后返回了3处并没构造好的实例引用,这时就可能产生错误*/
静态内部类
代码语言:javascript复制public class Singleton4 {
// 私有化构造函数
private Singleton4() {}
// 静态内部类
private static class SingletonInstance {
private static final Singleton4 instance = new Singleton4();
}
public static Singleton4 getInstance() {
return SingletonInstance.instance
}
}
枚举类
代码语言:javascript复制public enum Singleton5 {
// 枚举元素本身就是单例
INSTANCE;
// 自己的操作
public static method() {
//调用该方法会主动使用Singleton5,INSTANCE将会被实例化
}
}
// 推荐使用这种方式
小结:不建议使用双重锁判定机制,单例对象、资源占用少,枚举要比饿汉好,目前用的较多的是枚举。