饿汉模式:
重点是类加载的时候就会创建实例
1.私有化构造器;
2.创建一个实例;
3.创建一个方法来给其他类提供实例;
public class singleton{
private singleton(){}
private static singleton instance=new singleton();
public static singleton getInstance(){
return instance;
}
}
优点是:线程安全。因为在类加载的时候就完成实例化,避免了线程同步问题。
缺点是:有浪费内存的可能。如果从未使用过实例,那么会造成内存的浪费。调用实例方法会进行类加载,但也有其他可能也会导致类加载,这时候初始化instance就没有达到lazy loading的效果。
懒汉模式:
重点是只有在调用getInstance方法后才会构造实例 1.私有化构造器; 2.创建一个类的变量; 3.创建一个方法来构造实例并返回。
public class singleton{
private singleton(){}
private singleton instance;
public static singleton getInstance(){
if(instance==null){
instance=new singleton();
}
return instance;
}
}
优点:达到了懒加载的效果,但只有在单线程状态下才能使用;
缺点:线程不安全。如果一个线程进入了if中但还没有创建实例,此时另一个线程也进入if中,这便会产生多个实例。
加个synchronized锁在方法上可以解决线程同步问题,但缺点是效率太低:只需要在第一次时创建实例,其他时候只用直接return就够了,但这种同步是每次进入都有重新创建一遍,造成浪费。
ps:如果想在if中加个synchronized同步块来解决这个问题是错误的,没解决不说还会造成线程不安全。
双层检验
特点是判断两次if(instance==null)
1.构造器私有化
2.创建一个静态volatile属性;
3.创建一个共有方法来new并返回。
public class Singleton{
private Singleton(){}
private static volatile Singleton instance;
public statice Singleton getInstance(){
if(instance==null){
sychonized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
线程安全,效率高
静态内部类
特点是用静态内部类来new实例
1.构造器私有化;
2.创建一个静态内部类,里面构造一个静态属性并new;
3.创建一个公有方法来返回静态内部属性。
public class Singleton{
private Singleton(){}
private static class SingletonInstance{
private static final Singleton INSTANCE=new Singleton();
}
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
类加载的时候,实例不会初始化,因为SingletonInstance类没有被主动调用,只有显式调用了getInstance方法才会显式加载SingletonInstance,从而实例化instance。
注意内部类SingletonInstance要用static修饰且其中的静态变量INSTANCE必须是final的
优点:线程安全,效率高