自我java面试题的一些总结
一,HashMap底层及原理
1.jdk1.7和1.8时hash map的区别
jdk1.8对hash map进行了底层的优化,例如红黑树的数据结构和扩容的优化等。
jdk1.7:
使用数组+链表
Entry节点
它使用的是头插法
jdk1.8:
使用数组+链表+红黑树 在链表长度大于8的时候就变为红黑树
Node节点 node就是map里的一个内部类,他本身就是一个k-v
它使用的是尾插法
注:大于八就是树,小于六就变回链表
注:他为什么改成了尾插法,是因为使用头插有可能会造成环形链表。
2.hash map扩容
扩容:创建⼀个新的Entry空数组,⻓度是原数组的2倍。
ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。
第一步,他的扩容实际上就是对哈希表长度的拓展,扩容成原来的2倍,第二步就是将原来的数据挪到新的table上
为什么他要将哈希table的大小控制在2的次幂数?
原因:为了降低膨胀的概率,使散列更加均匀
这个是线程安全的么?
这个并不是线程安全的。
他有可能发生死循环,数据重复,数据丢失(覆盖)。
你想要保证他的线程安全的时候你会怎么做?
这时候就会有一个线程安全的–concurrentHashMap.
为什么选择concurrentHashMap?
因为他的并发度更高,在jdk1.8之后他也变成了数组+链表+红黑树 只会锁住当前节点的值。
并不像原来1.7jdk版本低的时候使用分片锁机制。
3.hash map默认初始化大小是16
二,多线程
1.首先我们要知道怎么实现线程
java中有四种办法1.实现runnable接口2.继承thread类3.实现Callable接口4.使用线程池
2.常用线程池
- newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 - newFixedThreadPool
创建一个指定工作线程数量的线程池 工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。 - newSingleThreadExecutor
创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务 - newScheduleThreadPool
创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。
三,Http协议
HyperText Transfer Protocol超文本传输协议 hai po tie chuansifou po ti kao
1.三次握手
浏览器向服务器发送请求
服务器回应请求
浏览器确认服务器的确认
2.四次挥手
浏览器发送FIN码给服务器,告诉服务器,数据传输完成了
服务器接受FIN码,然后发送ACK码给浏览器,告诉浏览器,你可以断开链接
服务器继续发送FIN+ACK码给浏览器,告诉浏览器,我数据发送完毕
浏览器接收到FIN+ACK码以后在发送ACK码给服务器,我接收到了,你可以断开连接了
HTTP请求方法(8种)
Get post head put delete trace options connect
三,mysql的事务
1.事务的四个特征
事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
1 、原子性。事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性。事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
3 、隔离性。一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性。也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
四种隔离级别
SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
2.事务的七大传播行为
PROPAGATION_REQUIRED
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则新建一个事务
3.为什么mysql默认隔离机制是可重复读
(1)隔离级别设为可重复读(Repeatable Read),在该隔离级别下引入间隙锁。当Session 1执行delete语句时,会锁住间隙。那么,Ssession 2执行插入语句就会阻塞住!
(2)将binglog的格式修改为row格式,此时是基于行的复制,自然就不会出现sql执行顺序不一样的问题!奈何这个格式在mysql5.1版本开始才引入。
出现问题
这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
四,Spring
1.java bean的生命周期
1.实例化(使用工厂方法,构造函数自动装配或简单实例化,为制定的bean创建一个实例)
2.属性填充(表面意思)
3.初始化(Aware相关回调,初始化前置处理,初始化,初始化后置处理)
4.销毁(表面意思)
2.IOC于AOP
(1)何为IOC
所谓控制反转就是你想要获取对象的时候,通过反射来获取对象。底层就是使用依赖注入模式。
IOC的核心就是不使用控制资源的双方管理,而是使用不控制资源的第三方进行管理。这样就让资源可以更好的进行调配,也降低了耦合度。
(2)何为AOP
所谓面向切面的编程,也就是说,它会把相对独立的功能抽取出来,然后在使用Spring的配置文件(XML)进行插入,可以说是实现了重复利用,而且大大减少了重复的代码量,并且使得以后的维护和管理更加方便了。
Aop中的jdk动态代理是通过反射机制实现的。(还有一个CGLIB的动态代理)
注:java中jdk的动态代理只能实现接口,而新型的CGLIB可以实现类的动态代理
注:以上仅代表个人意见,如果大家发现问题欢迎指正,本人只是小白一名,跟大家一起进步。
–甜橙棒棒糖