单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例
创建实例过程:
1.开辟一个空间
2.把内存空间的首地址指向引用
3.调用构造器创建实例
特点:
1.由自己创建实例
2.外部不能创建实例
3.提供一个公共方法供外部获得单例
创建方式:
1.饿汉式
饿汉式单例在类加载初始化时就创建好一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。
2.懒汉式
该示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个single对象
代码示例:
饿汉式:线程安全 缺陷:占用资源
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
懒汉式:非线程安全 延迟加载不占用资源
private static Singleton instance = null;
private Singleton(){}
//容易出现线程安全问题
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
懒汉式线程安全问题解决方法:双重加锁机制(双重判断+同步锁+volatile【防止不完整实例】)
不推荐:效率低,消耗资源
private static volatile Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
说明:volatile作用:在多线程访问下,若线程A正在创建实例时:开辟一块空间,把地址指向引用,还未调用构造器时,线程B判断引用不为null,这时返回一个不完整的实例,导致系统崩溃。该关键字就是防止暴露不完整实例发生
饿汉式占用资源解决方法:类级内部类(线程安全+延迟加载+效率高)推荐!!!
public class Singleton {
public static class Holder{
private static Singleton instance = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return Holder.instance;
}
}
说明:静态内部类和外部类没有从属关系,加载外部类的时候,并不会同时加载其静态内部类,只有在发生调用的时候才会进行加载,加载的时候就会创建单例实例并返回,有效实现了懒加载(延迟加载)