谈Array List和Linked List的区别 :
1、底层结构不同,Array List是基于数组实现的,Linked List是基于链表实现的。
2、底层结构不同,适用场景不同,Array List 适用于随机查找,Linked List适用于增添、删除。Linked List是双向链表
3、对于查询如果是指定下标的查询,Array List是要比Linked List要快的,但是Linked List是获取第一个和最后一个元素的话也是比较快的。
谈Hash Put中的Put方法 :
1、根据Key通过哈希算法和与运算得出数组下标。
2、如果数组下标为空,则将Key和Value封装为Entry对象(1.7是Entry对象,1.8是Node对象。)
3、元素不为空,1.7先判断是否需要扩容,如果扩容就进行扩容,不扩容生成Entry对象,并使用头插发添加到当前位置的链表中。
4、1.8先判断当前位置上的Node类型,看是红黑数Node还是链表Node, 如果是红黑树,则将Key和Value最为一个红黑树节点封装到红黑树中,过程中判断红黑树是否存在当前key,存在则更新value.
如果是链表节点,把Key和value封装为一个链表Node通过尾插法插入链表最后,因为是尾插法所以要遍历列链表,遍历过程中判断是否存在当前key,如果存在更新value,遍历完链表后,将新链表Node插入到链表中,插入链表会看到当前节点个数,如果超过8,则转换成红黑树。
5、将key 和 value封装位node插入到链表或红黑树中,在判断是否要进行扩容,需要扩容就扩容,不需要就介绍PUT方法。
谈Thread Local :
1、Thread Local 是Java中所提供的线程本地存储机制,利用该机制将数据缓存在某个线程内部,该线程可以在任意时刻,任意方法中获取缓存的数据。
2、Thread Local 底层是通过Thread Local Map来实现的,每个Thread 对象中存在一个Thread Local Map ,
Map的key为Thread Local对象,Map的value为需要缓存的值。
3、如果在线程中使用的 Thread Local会造成内存泄漏,因为当Thread Local 对象使用完之后,应该把设置的Key、Value回收,就是Entry对象回收,但线程池中的线程不会回收,而线程对象是通过强引用指向Thread Local Map 。Thread Local Map 也是通过强引用指向Entry对象,线程不被回收,Entry也不会被回收,从而出现内存泄漏,解决办法,在使用Thread Local对象之后,手动调用Thread Local的remove方法,手动清除Entry对象。
4、Thread Local经典的应用场景就是连接管理(一个线程持有一个连接,该连接对象可以在不同的方法之间进行传递,线程之间不共享同一个连接)
谈JVM中,那些是共享区,那些可以作为GC ROOT :
1、堆区和方法是所有线程共享的。栈、本地方法栈、程序计算器是每个线程独有的。
2、什么是gc root, JVM在进行垃圾回收时,需要找到垃圾对象,也就是没有被引用的对象,但是直接找垃圾对象是比较耗时的,所以反过来先找非垃圾对象,也就是正常对象,那么就需要去某些根中寻找,根据这些根的引用路径找到正常对象,而这些根有一个特征,就是只会引用其他对象,而不会被其他对象引用,例如 :栈中的本地变量、方法区中静态变量、本地方法栈中的变量、正在运行的线程等可以作为gc root.
谈如何查看线程死锁 :
1、可以通过jstack命令来进行查看,jstack命令中会显示发生了死锁的线程。
2、或者两个数据去操作数据库时。数据库发生了死锁,这是可以查询数据库的死锁情况。
线程之间是如何通信的
1、线程之间可以通过共享内存或基于网络来通信。
2、如果是通过共享内存来通信,则需要考虑并发问题,什么时候阻塞和唤醒。
3、像Java中的wait(),notify()就是阻塞和唤醒。
4、通过网络就比较简单了,通过网络连接将通信数据发送给对方,当然也要考虑并发问题,处理方式就是加锁等方式。
介绍一下Spring,读过源码介绍一下大致流程
1、Spring 是一个快速开发工具,Spring 来帮助程序员来管理对象。
2、Spring 的源码实现也是非常优秀的,设计模式的应用,并发安全的实现,面向接口的设计等。
3、在创建Spring容器中,也就是启动Spring中 :
首先会进行扫描,扫描得到所有的BeanDefinition对象,并存在一个Map中。
然后筛选出非懒加载的单例BeanDefinition进行创建bena,对于多例Bean不需要在启动过程中去进行创建,对于多例Bean会在每次获取Bean时利用BeanDefinition去创建。
利用BeanDefinition创建Bean就是Bean创建生命周期,这期间包括了合并BeanDefinition、推断构造方法、实例化、属性填充、初始化前、初始化、初始化后、其中AOP就是发生在初始化后这一步。
4、单例Bean创建完之后,Spring会发布一个容器启动事件。
5、Spring启动结束
6、在源码过程中会更复杂,比如源码中会提供一些模板方法,让子类来实现,比如源码中还涉及到一些BeanFactoryProcessor和BeanPostProcessor的注册,Spring的扫描就是通过BeanFactoryProcessor来实现的,依赖注入就是通过BeanPostProcessor来实现的。
7、在Spring启动过程中还会去处理@Import等注解。
说一下Spring的事务机制
1、Spring的底层时居于数据库事务和AOP机制的。
2、首先对于使用了@Transactional注解的Bean,Spring会创建一个代理对象作为Bean.
3、当调用代理对象的方法时,会先判断方法上是否加了@Transactional注解。如果加了,那么则利用事务管理器创建一个数据库连接。
4、并且修改数据库连接的autocommit属性为false,禁止此连接的自动提交,这是实现Spring事务非常重要的一步。
5、然后执行当前方法,方法会执行sql。
6、执行完当前方法后,如果没有出现异常就直接提交事务。
7、如果出现了异常,并且这个异常时需要回滚的就会回滚事务,否则仍然提交事务。
8、Spring事务的隔离级别对应的就是数据库的隔离机制,
9、Spring事务的传播机制时Spring事务自己实现的,也是Spring中事务最复杂的。
10、Spring事务的传播机制是基于数据库连接起来的,一个数据库连接一个事务,如果传播机制配置为需要新开一个事务,那么实际上就是先建立一个数据库连接,再此新数据库连接上执行SQL。