1.单例类特点
1.只能有一个实例。
2.必须自己创建自己的唯一实例。
3.必须给所有其他对象提供这一实例。
总结:单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2.代码
1)Singleton将构造方法限定为private避免了类在外部被实例化。so,Singleton的唯一实例只能通过getInstance()方法访问。
注:通过Java反射机制是能够实例化构造方法为private的类的(可自行研究)
2) synchronized//同一时刻最多只有一个线程执行该段代码
3) lazy loading 延迟加载
第一种懒汉单例模式 -线程不安全
<span style="font-size:18px;"> public class Singleton {
private Singleton() {}
private static Singleton single=null;
//静态工厂方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
} </span>
第二种 懒汉单例模式 -线程安全
这种写法效率很低,99%情况下不需要同步
<span style="font-size:18px;">public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}</span>
第三种 双重校验锁定(第二种方式的升级)
volatile:被设计用来修饰被不同线程访问和修改的变量,处理多并发,相当于对变量加锁,进行逐一处理
<span style="font-size:18px;"> public class Singleton {
private static volatile Singleton instance = null;
private Singleton (){}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
return instance;
}
} </span>
第四种 静态内部类,具有以上两种优点(相对于五、六种,实现了延迟加载)
内部类:在一个类中定义的类
既实现了线程安全,又避免了同步带来的性能影响。
<span style="font-size:18px;"> public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}</span>
第五种 饿汉单例模式 -线程安全
在类实例化时就已经创建好一个静态的对象供系统使用,线程是安全的。
这种方式基于classloder机制避免了多线程的同步问题,这时候初始化显然没有达到lazy loading(延迟加载)的效果
特点:
饿汉单例类在类初始化时,已经自动实例化
<span style="font-size:18px;"> public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}</span>
第六种 饿汉单例模式 -线程安全-没有达到lazy loading
<span style="font-size:18px;">public class Singleton {
private Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return this.instance;
}
}</span>
第七种 枚举
不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
<span style="font-size:18px;">public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
} </span>