1. 饿汉式,静态常量,可用
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
复制代码
优点:
- 写法简单
- 类加载的时候就完成了实例化
2. 饿汉式,静态代码块,可用
public class Singleton {
private final static Singleton INSTANCE;
static {
INSTANCE = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
复制代码
3. 懒汉式,线程不安全,不可用
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
复制代码
缺点:
- 线程不安全,多个线程会重复创建实例
4. 懒汉式,线程安全,同步方法,不推荐使用
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
复制代码
缺点:
- 效率低
5. 懒汉式,线程不安全,同步代码块,不可用
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
}
复制代码
6. 双重检查,推荐面试使用
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
复制代码
优点:
- 两次判断保证线程安全
- 延迟加载,效率较高
为什么要用volatile?
new Singleton()新建对象实际上有3个步骤,使用volatile可以防止重排序。
7. 静态内部类,推荐使用
public class Singleton {
private Singleton() {
}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
复制代码
优点:
- 线程安全
- 懒加载
8. 枚举,推荐使用(生产实践中最佳的单例写法)
public enum Singleton {
/**
* 实例
*/
INSTANCE;
/**
* 其它的方法...
*/
public void test(){
}
}
复制代码
其它类如何使用?
public static void main(String[] args) throws InterruptedException {
Singleton.INSTANCE.test();
}
复制代码
不同写法对比
- 饿汉:简单,但是没有懒加载
- 懒汉:有线程安全问题
- 静态内部类:可用
- 双重检查:面试用
- 枚举:最好
枚举为什么是最好的方法
1. Joshua Bloch大神在《Effective Java》中明确表达过的观点:“使用枚举实现单例的方法虽然还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法”。
2. 写法简单
3. 线程安全有保障
4. 避免反序列化破坏单例
各种写法的适用场合
- 最好的方法是利用枚举,因为还可以防止反序列化重新创建新的对象;
- 非线程同步的方法不能使用;
- 如果程序一开始要加载的资源太多,那么就应该使用懒加载;
- 饿汉式如果是对象的创建需要配置文件就不适用;
- 懒加载虽然好,但是静态内部类这种方式会引入编程复杂性。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END