【Java】基础知识

4-23 类的加载
      Java类的加载 是把.class文件的二进制的数据读取到内存中,将其放在运行时数据区的方法区内,并在堆区上创建java.lang.class对象,该对象封装了类在方法区的数据结构,给使用者提供了方法区内的数据结构相关接口。
      类加载器并不会等到 某个类被首次使用到,再加载他.JVM允许类加载器在某个即将被使用的时候,预先加载他.如果在预先加载的使用遇到了.class文件缺失或存在错误,类加载器将会在该类被首次使用时,才会报告错误.而如果没有被使用则不会报错。
类的加载过程包括 加载 验证 准备 解析 初始化.
类的加载有
1. 命令行启动应用时候由JVM初始化加载
2. 通过Class.forName()方法动态加载.
3. 通过ClassLoader.loaderClass()动态加载
      双亲委派机制:当一个类加载器收到一个请求时,他首先不会自己去加载这个类,还是将其将给父对象,并且接着向上传递,直至传递给启发式类加载器,由启发式类加载器加载.只有当搜索范围内没有找到所需的类,该类加载器才会主动尝试加载该类.

4-23 绑定
      将一个方法与类或者对象关联起来,叫做绑定.绑定分为两种,静态绑定和动态绑定.
      静态绑定:在方法运行前时,已经知道方法属于哪一个类了,那么在编译的时候就可以连接到类中,定位到那个方法.
      动态绑定:在程序运行过程中,根据具体的实例对象才能具体确定是哪个方法.
      每个类被加载到虚拟机时,在方法区保存元数据,其中包含一张方法表,这个表的每个项是指向具体方法的代码,如果这个类的方法被重写,那么这个表项将会指向新的代码.


4-23 volatile实现原理
      在Java虚拟机中,加了volatile和没有加volatile的汇编代码比较,多了一个lock前缀.该前缀相当于是加了一个内存屏障.它提供了三个功能:
1. 在lock后面的代码不会因为重排排到lock之前,lock之前的代码不会因为重排排到lock后面
2. 修饰的变量在缓存修改之后,会被强制写回内存.
3. 如果是写操作,会使其他CPU对缓存行无效.

4-27 ArrayList与LinkedList区别
      ArrayList是基于动态数组实现,所以在随机访问上比较占优势,但是如果要做增删操作的话,花费的时间就比较多了,因为要做数据移动操作.
      LinkedList则是基于双向循环链表,链表机制在随机读取方面因为指针的移动较慢,但是在添加删除操作中较为占优.

4-27 ThreadLocal工作原理
      主要说说ThreadLocal的get方法,首先用当前线程为参数,获得一个ThreadLocal的成员变量ThreadLocalMap,这里就存放了线程独有的数据,然后再以当前ThreadLocal对象为参数,获取线程独有的数据,如果说,没有就会进行一个初始化setInitialValue方法,这里也是相同的方法,通过当前线程获得一个map然后将当前对象作为key传入.

4-28 synchronized与ReentrantLock区别
      首先synchronized是由JVM实现,在其锁住的代码块之前加了monitorent,在代码块之后加了monitorexit.在执行monitorent时,会尝试获得锁,如果对象没有被锁定,或是当前线程已经获得对象锁,锁的计数器+1.在执行monitorexit的时候,会讲计数器-1.
      ReentrantLock则是基于API而成的,使用CAS(compare and swap)机制,包含三个属性:内存数据,旧的预期数据和修改值.我的理解是ReentrantLock是一种乐观锁,只有在内存数据与旧的预期数据相同时,才会把修改值改回内存.
      ReentrantLock有公平锁机制,还有读写锁的子类,更加灵活.

4-28 HashMap插入key为null
      正常在HashMap中是以HashCode为key,但是如果是null呢?在源码中,如果说插入key为Null那么,会执行一个PutForNullKey,这个方法会在原hashMap的array[0]这个做一个遍历查找key==null的键值对,如果有就直接覆盖.没有的话,就头插法,插入新键值对.

4-30 设计模式-模版模式
      模版模式 我的理解就是一开始先设定好一个模版,然后之后根据需要往里面填东西.
      比如说(别人的例子),我定好了一个模版烹饪,里面有三步骤:洗菜,烹饪,上菜.那么对任意一道菜都可以拆分成洗对应食材,烹饪,和上菜.
      模版模式的优点:
1. 具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构.
2. 代码复用的基本技术,在数据库中尤为重要.
3. 存在一种反向控制结构,通过一个父类调用其子类的操作,通过子类对父类的扩展增加新的行为,符合开闭原则.
(也许就是抽象?)
5-2 concurrentHashMap
      历时两天 大致概念搞清楚了
      先贴看的资料https://my.oschina.net/hosee/blog/639352
      HashMap是线程不安全的,因为可能会在扩容过程中,造成数据覆盖乃至死循环的问题.
      所以出了一个替代品ConcurrentHashMap他将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个数据段的时候,其他线程也可以访问其他的锁下的数据.内部实现是,ConcurrentHashMap内部分为很多个Segment,每一个Segment拥有一把锁,这个Segment集成ReentrantLock,表明每一个Segment都可以当作一个锁.
      ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁.
      ConcurrentHashMao删除节点时,会将删除节点之前的所有节点拷贝一份形成一个新的链再将删除节点后的节点连接在拷贝链之后,这样在删除以后,有两条链存在.这样能保证如果有线程正在访问链的时候,依然访问原本的链.
      在执行put(),get()这样操作的时候,会首先将keyHash化,然后根据ConcurrentHashMap的concurecyLevel(描述Segment的个数)进行右移,从而确定这个HashEntry落在哪一个Segment里.
      在执行size()方法的时候,由于并发操作,size()会发生变化,正常来说要取得所有的Segment,才能进行,但是作者先执行三次遍历Segment,累加Segment的大小得到整个Map的大小,同时会记录每一个Segment的modCount变量(用来描述更新的次数),如果相邻的modCount和相同,那么说明Map没有更新操作,直接返回就行了.否则再取得所有Segment,再进行计算.

5-8 GC Root对象
1. 虚拟机栈中引用的对象
2. 本地方法栈静态属性引用对象
3. 本地方法栈常量引用对象
4. 方法区中JNI引用对象

5-8 Java什么时候会有内存泄漏
1. 使用类似HashMap,Vector等集合类的时候,如果将它设成static,那么他的生命周期和程序一样长.可能引起内存泄漏.比如说:一直有一个对象在new ,然后将它加入集合.
2. 同样是集合,如果加入集合的对象属性改变了,那么就无法将集合内的对象被删除,导致内存泄漏.
3. 数据库,网络,IO操作建立连接之后,如果不显式调用.close()方法,则Java虚拟机不会对其回收,导致内存泄漏.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值