当前位置 博文首页 > 平流层:java的单例模式小知识点

    平流层:java的单例模式小知识点

    作者:平流层 时间:2021-02-19 20:32

    单例模式

    目的

    为了让一个类有且仅有一个实例

    优点

    1. 只允许一个,节省空间

    2. 不用频繁创建删除,提高性能

    缺点

    1. 不容易扩展
    2. 长期不使用会被系统当作垃圾回收,造成系统状态的丢失

    实现

    要点

    1. 防止外界随意的创建对象=》一个私有的构造函数
    2. 保证只有一个实例 =》在私有静态属性中进行声明(饿汉创建,懒汉声明)
    3. 提供这个实例 =》提供静态的公有方法创建和获取私有对象

    代码

    问题

    //会不会报错?
    public class test {
        public static void main(String[] args) {
            Sun sun1=new Sun();
        }
    }
    class Sun{
        Sun sun=new Sun();//它会一直创建Sun对象,解决:用static修饰
    }
    
    //运行结果
    //Exception in thread "main" java.lang.StackOverflowError
    //	at com.imooc.Sun.<init>(test.java:10).....
    

    为什么会报StackOverflowError异常?

    图片解释:
    第4行开始在栈内存中声明一个叫s的sun对象,并指向堆内存中地址为“0xA”的Sun对象,此时地址“OxA“的Sun对象中有一个实例化本类的属性,所以它又指向地址"0xB" 的Sun对象,此时地址"0xB" 中有一个Sun类型的属性......所以会一直创建Sun对象,出现栈溢出

    饿汉式

    //饿汉式
    public class SingletonTwo {
        //私有构造函数
        private SingletonTwo(){ 
        }
        /**私有静态属性
        	为什么加static,假设不加static,就不能保证只有一个实例,可能会出现上面的问题
        	为什么加private,假设不加private,外界就可以用SingletonTwo.instance=null,把你对象置为空,有危险
        */
        private static SingletonTwo instance=new SingletonTwo();
    	/**公共返回
    		为什么加static,不加static访问该方法的话需要进行实例化,但是该类已经把构造方法私有化,没办法实例,所以只能用static通过“类名.方法名()”调用
        */
        public static SingletonTwo getInstance(){
            return instance;
        }
    }
    

    每次调用前就实例化好了,空间换时间,提前加载以后调用更快

    懒汉式

    //懒汉式
    public class SingletonOne {
        private SingletonOne(){
    
        }
        private static SingletonOne instance=null;
    
        public static SingletonOne getSingletonInstance(){
            if (instance==null)//一定要判断
                instance= new SingletonOne();
            return instance;
        }
    }
    
    

    只有每次调用的时候才会实例化,时间换空间,但是当多线程同时访问这个方法时,会存在危险

    比如有线程thread1和thread2,thread1第一次运行到第9行,满足条件正准备向下执行时,thread2抢到了执行权限,thread2直接调用getSingletonInstance方法创建了一个SingletonOne对象,thread2执行完后,thread1继续刚才的执行,从第10行开始,最后又创建了一个SingletonOne对象,此时就不满足只创建一个实例的条件了
     解决:给getSingletonInstance()方法加锁
    

    使用场景

    1. 对系统内资源同意读写的,配置文件,如mysql的名字,数据库名,账号密码
    2. 创建对象资源过多
    bk
    下一篇:没有了