java基础二

1. HashMap

1
2
3
4
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
.....
}

未完待续….仍需要查阅大量资料学习….

2.Java 内存分配

  • 栈区:方法区内的局部变量,对象的引用等 优点:速度快,缺点:大小和生命周期必须是确定的。
  • 堆区:new出来的对象,垃圾回收器回收的是堆区的内存
  • 方法区(静态区):静态变量,常量,保存类信息

3.垃圾

什么是垃圾?要通过科学的方法才能判断是否是为垃圾,有两种方法

  • 引用计数法:可能会导致内部循环
  • 可达性分析:是否可达

借助一个图快速理解 引用计数法

image.png

代码:

1
2
3
4
5
6
7
8
9
10
11
12
/**循环问题*/
public class Demo{
public Demo instance;
public static void main(String[] args) {
Demo a=new Demo();
Demo b=new Demo();
a.instance=b;
b.instance=a;
a=null;
b=null;
}
}

再看下这个 可达性分析

image.png

ObjDObjE 虽然内部存在引用,但是定点不可达,所以也是垃圾回收的对象。

4.垃圾回收的方法

  • 标记-清除:减少停顿时间,但会造成内存碎片

  • 标记-整理:可以解决内存碎片,但是会增加停顿时间

  • 复制清除:从一个地方拷贝到另一个地方,适合有大量回收的场景,比如:新生代回收

    • 优点:效率高于标记清除,活着的对象是整齐排列的,没有内存碎片
    • 缺点: 浪费空间,毕竟如果按照1:1比例划分空间的话,那么将会有50%的空间被浪费。不过在jvm中,新生代空间并不是按照1:1来划分的,而是按照8:1:1的比例分为一个eden 区 和两个survivor(survivor0,survivor1) 区,然后一个eden 区,两个survivor 区。大部分对象在Eden 区中生成。回收时先将eden 区存活对象复制到一个survicor0 区,然后清空eden 区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1 区,然后清空eden 区和survivor0 区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空,这样的过程也叫做Minor GC,每进行Minor GC 一次,存活着的对象的年龄就会+1,当存活着的对象的年龄到达15岁时,就会被送进年老代。 当然,当整个survivor1区不足以存放Edensurvivor0的存活对象时,也会将存活对象直接放到年老代。若是年老代也满了就会触发一次Full GC,也就是新生代,老年代都进行回收。
  • 分代收集:把内存区域分成不同代,根据年代不同采取不同的策略;

    • 新生代:存放新创建的对象,采用复制回收方法
    • 年老代:这些对象垃圾回收的频率较低,采取标记整理法
    • 永久代:存放Java本身的一些数据,当类不再使用时,也会被回收

    手稿:

image.png

5. Full GC 触发的条件

  • 调用 System.gc 时,系统建议执行Full GC 但是不必然执行
  • 年老代或者永久代空间不足

6. 线程调度

  • wait() : object 方法,必须在同步代码块中使用,使当前线程处于等待状态,释放锁
  • notify() : 和 wait 联合使用,通知一个线程,具体通知哪个由jvm 决定,使用不当可能发生死锁
  • notifyAll() : 和wait 方法联合使用,通知所有线程,具体哪个线程获得运行权 jvm 决定
  • sleep() : 睡眠状态

7.线程同步

  • Synchronzied 修饰
  • ThreadLocal : 每个线程都有一个局部变量的副本,互不干扰。一种以空间换时间的方式。
  • 线程安全的容器和方法,可以实现线程同步,如: Collections.SynchronizedList()List 转为线程同步;用ConurrentHashMap 实现hashmap 线程同步。

volatile 修饰的变量不会缓存在寄存器中,每次使用都会从主存器中读取;保证可见性,不保证原子性

-------------本文结束感谢您的阅读-------------