没有合适的资源?快使用搜索试试~ 我知道了~
Java面试题-Doocs开源社区.docx
需积分: 5 260 浏览量
2023-01-30
18:39:58
上传
评论
收藏 12.95MB DOCX 举报
Java面试题-Doocs开源社区
资源推荐
资源详情
资源评论
















开篇词
从技术角度而言:技术广度(面试突击一二三季)、技术深度(阅读源码、项目深度、开源社区)、项目经
验(2C、2B、政企、金融、电信、CRUD)、架构设计(负责过的架构有多大,你能设计多大多复杂的架
构)、基础知识(数据结构和算法、计算机组成原理、操作系统、网路协议)
从综合角度而言:管理能力,学历,履历,软素质(表达能力、沟通能力、团队协作、价值观、性格),
薪资要求
面试突击三季都学完 + 自己在面试过程中如果发现有一些问题是自己不会,要额外看一些书籍、或者别
的课程、或者别的资料做一些补充
视频地址: https://apppukyptrl1086.pc.xiaoe-tech.com/index
工作原理(How it works)剖析
所谓某个技术的工作原理,就是这项技术优缺点,怎么运行的(从了解其技术名词开始),图形化展示,而不仅仅
只会用它的 api 接口,
基础篇
Java 集合包
为什么在 Java 面试中一定会深入考察 HashMap?
HashMap 的深入考察,必然是面试中的一个核心的点
都是写 Java 代码,基于 Java 都是来构建各种各样的系统的,软件的,基于 Java 写出来一大堆的代码,可
能会访问很多其他的东西,数据库,缓存,消息中间件,核心还是来写 Java 代码实现一些逻辑的运转
接收到一个请求,可能会创建一些数据结构,来存放一些数据,做一些循环、跳转、判断、加加减减,数
据处理,逻辑,通过一大堆的逻辑就可以完成一些系统功能,或者是软件的功能
HashMap,数据结构,进行一定的逻辑的处理
一句话总结:你是 Java 工程师,你写代码的时候必然会用到一些数据结构,其中尤为经典的就是
HashMap,别人必然会考察你
你知道 HashMap 底层的数据结构是什么吗?
HashMap<String, String> map = new HashMap<String, String>();
map.put(“张三”, “测试数据”);
map.put(“李四”, “测试数据”);
{
“张三”: “测试数据”,
“李四”: “测试数据”
}
底层最核心的数据结构是数组

对张三计算出来一个 hash 值,根据这个 hash 值对数组进行取模,就会定位到数组里的一个元素中去
[<>, <>, <>, <>,<张三, 测试数据>, <>,<>,<李四, 测试数据>,<>, <>, <>, <>,<>, <>, <>, <>]
假设可以放 16 个元素,取模,index
array[4] = <张三, 测试数据>
map.get(“张三”) -> hash 值 -> 对数组长度进行取模 -> return array[4]
JDK 1.8 中对 hash 算法和寻址算法是如何优化的?
map.put(“张三”, “测试数据”)
对“张三”这个 key 计算他的 hash 值,是有一定的优化的
hash 算法优化
// JDK 1.8 以后的 HashMap 里面的一段源码
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
比如说:有一个 key 的 hash 值
1111 1111 1111 1111 1111 1010 0111 1100
0000 0000 0000 0000 1111 1111 1111 1111
1111 1111 1111 1111 0000 0101 1000 0011 -> int 值,32 位
hash 值一样 -> 他们其实都会在数组里放在一个位置,进行复杂的 hash 冲突的处理
[16 个元素] -> hash 值对数组长度取模,定位到数组的一个位置,塞进去就 ok 了
高低 16 位都参与运算
你知道 HashMap 是如何解决 hash 碰撞问题的吗?
hash 冲突问题,链表+红黑树,O(n)和 O(logn)
map.put 和 map.get -> hash 算法优化(避免 hash 冲突),寻址性能优化
算出 key 的 hash 值,到数组中寻址,找到一个位置,把 key-value 对放进数组,或者从数组里取出来
两个 key,多个 key,他们算出来的 hash 的值,与 n-1,与运算之后,发现定位出来的数组的位置还是一
样的,hash 碰撞,hash 冲突
[<> -> <> -> <>, ]
array[0]这个位置,就是一个链表
会在这个位置挂一个链表,这个链表里面放入多个元素,让多个 key-value 对,同时放在数组的一个位置
里

get,如果定位到数组里发现这个位置挂了一个链表,此时遍历链表,从里面找到自己的要找的那个 key-
value 对就可以了
假设你的链表很长,可能会导致遍历链表,性能会比较差,O(n)
优化,如果链表的长度达到了一定的长度之后,其实会把链表转换为红黑树,遍历一颗红黑树找一个元素,
此时 O(logn),性能会比链表高一些
说说 HashMap 是如何进行扩容的可以吗?
默认初始化长度为 16
底层是一个数组,当这个数组满了之后,他就会自动进行扩容,变成一个更大的数组,让你在里面可以去
放更多的元素
2 倍扩容
[16 位的数组,<> -> <> -> <>]
[32 位的数组,<> -> <>, <>]
数组长度=16
n - 1 0000 0000 0000 0000 0000 0000 0000 1111
hash1 1111 1111 1111 1111 0000 1111 0000 0101
&结果 0000 0000 0000 0000 0000 0000 0000 0101 = 5(index = 5 的位置)
n - 1 0000 0000 0000 0000 0000 0000 0000 1111
hash2 1111 1111 1111 1111 0000 1111 0001 0101
&结果 0000 0000 0000 0000 0000 0000 0000 0101 = 5(index = 5 的位置)
在数组长度为 16 的时候,他们两个 hash 值的位置是一样的,用链表来处理,出现一个 hash 冲突的问题
如果数组的长度扩容之后 = 32,重新对每个 hash 值进行寻址,也就是用每个 hash 值跟新数组的 length -
1 进行与操作
n-1 0000 0000 0000 0000 0000 0000 0001 1111
hash1 1111 1111 1111 1111 0000 1111 0000 0101
&结果 0000 0000 0000 0000 0000 0000 0000 0101 = 5(index = 5 的位置)
n-1 0000 0000 0000 0000 0000 0000 0001 1111
hash2 1111 1111 1111 1111 0000 1111 0001 0101
&结果 0000 0000 0000 0000 0000 0000 0001 0101 = 21(index = 21 的位置)
判断二进制结果中是否多出一个 bit 的 1,如果没多,那么就是原来的 index,如果多了出来,那么就是 index
+ oldCap,通过这个方式,就避免了 rehash 的时候,用每个 hash 对新数组.length 取模,取模性能不高,
位运算的性能比较高

Java 并发编程
BAT 面试官为什么都喜欢问并发编程的问题?
synchronized 实现原理、CAS 无锁化的原理、AQS 是什么、Lock 锁、ConcurrentHashMap 的分段加锁的
原理、线程池的原理、java 内存模型、volatile 说一下吗、对 java 并发包有什么了解?一连串的问题
写一些 java web 系统,运用一些框架和一些第三方技术,写一些类似于 crud 的业务逻辑,把各种技术整
合一下,写一些 crud 而已,没什么技术含量。很多人可能写好几年的代码,都不会用到多少 java 并发包
下面的东西
如果说你要面试一些稍微好一点的公司,技术稍微好一点,你只要去做一个技术含量稍微高一点的系统,
并发包下面的东西还是很容易会用到的。尤其是 BAT,中大厂,有一定规模的公司,做出来的系统还是有
一定的技术含量的
说说 synchronized 关键字的底层原理是什么?-(基础篇)
计数器
之前有一些同学去一线互联网大厂里去面试,聊并发编程这块的内容,问的比较深一点,就说 synchronized
的底层原理是什么呢?他当时就答不出来了
如果我要是对 synchronized 往深了讲,他是可以很深很深的,内存屏障的一些东西,cpu 之类的硬件级别
的原理,原子性、可见性、有序性,指令重排,JDK 对他实现了一些优化,偏向锁,几个小时
面试突击第三季,快速过一下常见的高频面试题而已
其实 synchronized 底层的原理,是跟 jvm 指令和 monitor 有关系的
你如果用到了 synchronized 关键字,在底层编译后的 jvm 指令中,会有 monitorenter 和 monitorexit 两个
指令
monitorenter
// 代码对应的指令
monitorexit
那么 monitorenter 指令执行的时候会干什么呢?
每个对象都有一个关联的 monitor,比如一个对象实例就有一个 monitor,一个类的 Class 对象也有一个
monitor,如果要对这个对象加锁,那么必须获取这个对象关联的 monitor 的 lock 锁

他里面的原理和思路大概是这样的,monitor 里面有一个计数器,从 0 开始的。如果一个线程要获取 monitor
的锁,就看看他的计数器是不是 0,如果是 0 的话,那么说明没人获取锁,他就可以获取锁了,然后对计
数器加 1
这个 monitor 的锁是支持重入加锁的,什么意思呢,好比下面的代码片段
// 线程 1
synchronized(myObject) { -> 类的 class 对象来走的
// 一大堆的代码
synchronized(myObject) {
// 一大堆的代码
}
}
加锁,一般来说都是必须对一个对象进行加锁
如果一个线程第一次 synchronized 那里,获取到了 myObject 对象的 monitor 的锁,计数器加 1,然后第
二次 synchronized 那里,会再次获取 myObject 对象的 monitor 的锁,这个就是重入加锁了,然后计数器
会再次加 1,变成 2
这个时候,其他的线程在第一次 synchronized 那里,会发现说 myObject 对象的 monitor 锁的计数器是大
于 0 的,意味着被别人加锁了,然后此时线程就会进入 block 阻塞状态,什么都干不了,就是等着获取锁
接着如果出了 synchronized 修饰的代码片段的范围,就会有一个 monitorexit 的指令,在底层。此时获取
锁的线程就会对那个对象的 monitor 的计数器减 1,如果有多次重入加锁就会对应多次减 1,直到最后,
计数器是 0
然后后面 block 住阻塞的线程,会再次尝试获取锁,但是只有一个线程可以获取到锁
能聊聊你对 CAS 的理解以及其底层实现原理可以吗?(基础篇)
取值,询问,修改
多个线程他们可能要访问同一个数据
剩余486页未读,继续阅读
资源评论

晨港飞燕
- 粉丝: 685
- 资源: 33

上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助

会员权益专享
安全验证
文档复制为VIP权益,开通VIP直接复制
