类型:它是一种创建类模式。
在平时开发的时候,无论是自己写还是看别人的代码,可能随时都会看到单例模式。可能有的人都写得不爱了。但是我还是想根据我的见解来说说它。
单例模式就是确保一个类只有一个实例,并提供一个访问它的全局访问点。单例模式写法有好几种。
- 饿汉式:private static Singleton uniqueInstance = new Singleton();
- 懒汉式: private static Singleton uniqueInstance = null;
Java里面实现的单例是一个虚拟机的范围。因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoader装载饿汉式实现单例类的时候就会创建一个类的实例。
懒汉式单例有延迟加载和缓存的思想。
懒汉式单例
//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
private Singleton() {}
private static Singleton single=null;
//静态工厂方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
饿汉式单例
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}
饿汉式与懒汉式的区别
- 懒汉式是典型的时间换空间,饿汉式是典型的空间换时间
- 不加同步的懒汉式是线程不安全的。比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,就可能导致并发问题。饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。
如何保证懒汉式的同步问题
- 1.同步方法
public static synchronized Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; }
但这样会降低整个访问的速度,而且每次都要判断。可以用双重检查加锁。
2.双重检查加锁
双重加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例。这是第二重检查。
双重加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。public class Singleton { /** * 对保存实例的变量添加volitile的修饰 */ private volatile static Singleton instance = null; private Singleton(){ } public static Singleton getInstance(){ if(instance == null){ synchronized (Singleton.class) { instance = new Singleton(); } } return instance; } }
单元素的枚举类型实现单例
根据《Effective Java第二版》中的说法,单元素的枚举类型已经成为实现Singleton的最佳方法。
public enum Singleton { singleton; private Singleton () { } }
如有不妥,欢迎指出。哈哈哈哈