zoukankan      html  css  js  c++  java
  • 对Java中堆栈的解析

                                                                                      Java把内存分为两种:一种是栈内存,一种是堆内存

    栈内存:在函数中定义的一些基本类型的变量和对象的引用变量,当超过变量的作用域之后,Java自动释放该变量内存

    堆内存:存放new创建的对象和数组,由JVM的GC(Java虚拟机的自动垃圾回收器)管理

    附加1:跟C++不一样,Java自动管理栈和堆

    栈的  优势:存取速度快,栈数据可以共享(具体参考附加2)

              缺点:存在栈中的数据大小跟生存周期必须是确定的,不灵活

    堆的   优势:动态的分配内存,不必有个确定的数值,GC会自动回收垃圾数据

               缺点:存取速度慢

    附加2:为什么栈的数据可以共享?

                  执行int a = 3,int b =3,先在栈中创建一个变量为a的引用,然后在栈中找有没有字面值为3的地址,如果没有,就开辟一个存放字面值为3的地址,如果有就将引用变量a指向字面值为3的这个地址,现在执行完了int a = 3,之后,栈中有一个引用变量a和一个字面值为3的地址,且引用变量a指向字面值为3的地址,然后执行int b = 3,创建一个引用变量b,然后找字面值为3的地址,因为前面创建了,所以可以找到,所以让引用变量值指向字面值为3的地址,所以引用变量a和b都指向同一个字面值为3的地址,达到了数据共享的目的

    Java中的数据类型:

    有两种,第一种是基本的数据类型,8种即:int,short,long,byte,float,double,boolean,char(注意注意!没有String类型),大小可知,所以存于栈中,第二种是包装类的数据,如Integer,String,Doubel,目的是方便数据类型的转换,存于堆中

    1 public static void main(String[] args) {
    2        String a = "123";
    3        int b = Integer.valueOf(a);//包装类存在的目的是为了方便进行数据类型的转换
    4        System.out.println(b+1);
    5     }

    对特殊包装类String的分析:

    先分析String str = "abc"的内部工作

    1.定义一个叫做str的String类型的对象引用变量

    2.在栈中查找有没有存放值为"abc"的地址,如果没有,就开辟一个存放值为"abc"的地址,接着在堆中创建一个新的String类对象o,且将o的字符串值指向这个地址,在栈中这个地址的旁边记下引用对象o,如果已经有了值为"abc"的地址,则查找对象o,返回o的地址

    3.将str这个对象引用变量指向对象o的地址

    4.结束

    对String str = "abc"的正确解释:定义了一个引用变量指向"abc"这个String类型的对象

    这种情况下,其在堆中对象的字符串值指向栈中的引用,即字符串值指向引用

     1 String str1 = "abc"; String str2 = "abc";

    2 System.out.println(str1==str2); //true //“==”在JDK中只有两个引用都指向了同一个对象才返回真

    说明两个不同的引用变量都指向了同一个对象

    进一步说明:

    1 String str1 = "abc"; 
    2 String str2 = "abc"; 
    3 str1 = "bcd"; 
    4 System.out.println(str1 + "," + str2); //bcd, abc 
    5 System.out.println(str1==str2); //false 

    赋值的变化导致了对象的变化,str1指向了一个新的对象,而str2还是指向一个原来的对象

     1 String str1 = "abc";

    2 String str2 = new String("abc");

    3  System.out.println(str1==str2); //false  

    分析:俩个不同的引用,指向两个不同的对象,说明new在堆中创建的对像,不会共享栈中的数据

    附加3:String和String Buffer和String Builder的优缺,区别

    String:长度大小不可变,当字符串需要经常变化的时候,不要使用,会降低程序速度

    String Buffer和String Builder:长度可变

    String Buffer:线程安全,多线程的时候建议使用

    String Builder:线程不安全,比String Buffer速度快,单线程的时候建议使用

    附加4:什么叫做线程不安全?         

    即多线程运行的时候出现的数据不一致型,举一个非常生动形象的例子,线程安全也可以说是同步,同步就是说要等前面的请求完后,后面的才可以操作

    线程不安全可以说是异步,异步不用等待前面的请求,从效率上说,异步比同步快NN倍 ,摘自:http://bbs.csdn.net/topics/350181982

    /////

    打个比方,你和你老婆共用一张银行卡。忽然有一天,你去银行取钱,先查了一下余额有2000块钱,你想想取1500吧。刚巧这时候你老婆在网上看上一件800块钱的衣服,趁这功夫买下来了。你不知道钱被扣掉了,于是怎么都取不出来这1500。

    线程同步也是这个意思,当多线程运行时,他们可能会调用同样的资源,他们之间也不会互相通气,如果不采取措施,就有可能导致上面的问题。线程不是人,他取不到钱的时候不会就这么走了,要么死等导致deadlock,要么直接崩溃。线程安全就是要实现多线程时运行的结果和单线程时一样。明白了么?

     ///////////////////

    总结就是多线程运行的时候他们可能调用相同的资源,但是他们互不通气,各自干各自的,就叫线程不安全

    Java中内存分配策略

    3种:静态的,栈式的,堆式的

    静态内存分配策略:要求代码中不允许有可变的数据结构,比如可变数组,不允许嵌套递归

    栈式内存分配策略:又叫动态分配,在编译时对数据趣的需求是未知的,只有运行的时候才知道,但是在程序的入口必须告诉程序,这样才能确定程序块的需求内存大小来进行分配

    堆式内存分配策略:负责在编译时或者程序的入口时都无法确定储存要求的内存分配,比如对象实例和可变的字符串,堆由大片的可利用块或者空闲块组成,可以按照任意顺序分配和释放内存

    java中对象的内存分配:

    Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分 配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存

    只是一个指向这个堆对象的引用而已

    相关资料:http://blog.csdn.net/wulianghuan/article/details/8602254

    心之所向,素履以往
  • 相关阅读:
    [设计模式] 10 外观模式 facade
    [设计模式] 11 享元模式 Flyweight
    [设计模式] 9 装饰者模式 Decorator
    [设计模式] 8 组合模式 Composite
    float2int
    《ASP.NET》数据绑定——GridView
    Android Studio左边栏Project不见了?
    Linux下的五种I/O模型
    Shell编程入门(第二版)(下)
    Android訪问网络,使用HttpURLConnection还是HttpClient?
  • 原文地址:https://www.cnblogs.com/yinbiao/p/8073999.html
Copyright © 2011-2022 走看看