单例模式对大家来说应该都不陌生,不管是面试还是工作中大家都会避免不了要去使用,现在呢,咱们就来看看单例模式中最常见的四个模板是啥样的,分析其优点和缺点:
public class Singleton1 {
/**
* @category 饿汉模式 lazy loading
* @author fengzi
*/
private static class SingletonHolder{
private static final Singleton1 INSTANCE = new Singleton1();
}
public Singleton1(){
}
public static final Singleton1 getInstance(){
return SingletonHolder.INSTANCE;
}
public void test(){
System.out.println("饿汉来啦!");
}
public static void main(String[] args) {
Singleton1.getInstance().test();
}
}
public class Singleton2 {
/**
* @author fengzi
* @category 懒汉模式
*/
private volatile static Singleton2 singleton;
private Singleton2(){}
public static Singleton2 getInstance(){
if(singleton==null){
synchronized(Singleton2.class){
if(singleton==null){
singleton = new Singleton2();
}
}
}
return singleton;
}
public void test(){
System.out.println("Haha!");
}
public static void main(String[] args) {
Singleton2.getInstance().test();
}
}
饿汉模式:在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
懒汉模式:在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢
比较:饿汉模式由于在类初始化时候已经创建实例,因为不存在线程安全问题,而懒汉模式是在运行时创建实例,因此需要进行同步,来确保线程安全。
public enum Singleton3 {
/**
* @author fengzi
* @category 枚举方式
*/
INSTANCE;
private Singleton3(){
}
public void test(){
System.out.println("Haha!");
}
public static void main(String[] args) {
Singleton3.INSTANCE.test();
}
}
优点:
1. 自由序列化
2. 保证只有一个实例(即使使用反射机制也无法多次实例化一个枚举量);
3. 线程安全;
public class Singleton4 {
/**
* @author fengzi
* 静态内部类
*/
private static Singleton4 singleton = null;
static class Nested {
singleton = new Singleton4();
}
public Singleton4 getInstance(){
return singleton;
}
}
原理就是Java中静态内部类可以访问其外部类的成员属性和方法,同时,静态内部类只有当被调用的时候才开始首次被加载,因为java机制规定,内部类Nested 只有在getInstance()方法第一次调用的时候才会被加载(实现了lazy),而且其加载过程是线程安全的(实现线程安全)。内部类加载的时候实例化一次instance。