什么是单例?
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点;
分类
懒汉式:private static Singleton uniqueInstance = null;
饿汉式:private static Singleton uniqueInstance = new Singleton();
功能: 单例模式是用来保证这个类在运行期间只会被创建一个类实例,另外,单例模式还提供了一个全局唯一访问这个类实例的访问点,就是getInstance方法。
范围:Java里面实现的单例是一个虚拟机的范围。因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoader装载饿汉式实现单例类的时候就会创建一个类的实例。
懒汉式单例有延迟加载和缓存的思想
优缺点
懒汉式是典型的时间换空间
饿汉式是典型的空间换时间
⊙不加同步的懒汉式是线程不安全的。比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,就可能导致并发问题;
⊙饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的;
实现方式比较(非枚举)
1、饿汉式【可用】
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
2、懒汉式(线程不安全)【不可用】
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
虽然实现了延迟加载的效果,但是只能在单线程中使用,在多线程情况下无法保证实现单例;
3、懒汉式(线程安全、同步方法)【不推荐用】
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
解决了上面线程不安全的问题,但是每次在获取实例的时候都要进行同步,导致效率低下,得改进;
4、懒汉式(双重检查)【可用】
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
Double-Check概念对于多线程开发者来说不会陌生,这样做到了线程安全,延迟加载,效率较高。
5、懒汉式(静态内部类)【推荐】
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
类级的内部类,也就是静态类的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,而且只有被调用时才会装载,从而实现了延迟加载,效率高!
网友评论