工作了多年,做过C#,java,一直奋斗在一线coding领域。由于年龄,学历,管理经验综合因素,目前找不到工作了,现把多年积累的java面试八股文 分享出来。希望能给朋友们带来一点帮助。大家不用相信答案,只是本人个人理解。持续更新中......
1.JAVA基础篇
1.1 List与数组的区别
答:1.List 非固定长度,数组固定长度
2.ArrayList 底层实现基于数组,不支持非引用类型
3.List 插入 删除效率低于数组,功能比数组强大
1.2 HashMap
1.2.1 底层数据结构?1.7与1.8对比
答:1.jdk7 数组+链表 2.jdk8 数组+链表/红黑树 解决树不均衡问题
1.2.2 HashMap如何解决哈希冲突
答:链表法,将相同的hashCode值放在链表存储
1.2.3 线程是否安全?如何解决线程安全问题
答:非线程安全,可以使用Concurrenthashmap/HashTable
1.3 Concurrenthashmap
1.3.1 Concurrenthashmap如何保证线程安全
答:加锁保证线程安全,jdk1.7 是数组+链表实现的,对数组下标加锁处理保证线程安全,基于ReentrantLock 加锁 ,jdk1.8 数组+链表/红黑树实现。头部节点加锁,锁粒度更小,是通过 CAS 或 synchronized 来实现线程安全的
1.3.2 简叙下Concurrenthashmap的Get与Set流程
答:暂无
1.4 HashTable
1.4.1 与HashMap区别,是线程安全的吗?
答:基于HashMap实现,在put ,get时候加上了synchronized修饰 保证线程安全性
1.5 TreeMap
1.5.1 与HashMap区别?底层实现?使用场景哪些?
答: 区别:底层实现方式不同,TreeMap基于红黑树实现的
2.TreeMap可以实现自定义排序
3.TreeMap key 不能为Null
使用场景:自定义排序的Map可以用TreeMap
2.设计模式
2.1 单例模式
2.1.1 单例模式实现方式有哪些,优缺点? 具体应用场景?
答:1.饿汉式单例 优点:执行效率高 无锁 缺点:浪费内存
2.懒汉式单例 优点:节省内存 缺点:非线程安全
3.双写检查懒汉式单例 优点:节省内存 线程安全 缺点:效率低下
4.容器式单例 Spring IOC推荐
实际框架应用:Spring IOC
3.多线程
3.1 线程有几种状态?各个状态之间如何切换
答:1.线程有7种状态 分别是NEW,READY,RUNNING,WAITING,TIME_WAITING,BLOCKED,TERMINATED
2.NEW是初始化状态,实例化线程时候产生的状态new Thread
3.READY是就绪状态,线程调用start方法时候等待CPU调用产生
4.RUNNING是运行状态,CPU调度运行状态
5.WAITING是等待状态,TIME_WAITING是超时等待,等待某个线程的特定操作才会被唤醒
6.BLOCKED是阻塞状态,只有 Synchronized 同步锁等待才会存在这个状态
7.TERMINATED是终止状态
线程状态切换
1.实例化线程NEW状态->等待CPU调用READY状态->Synchronized抢锁 失败BLOCKED状态->抢锁成功RUNNING状态->主动/被动执行结束TERMINATED状态
2.Thread.yeild(),notify(),unpark() 可以使线程进入READY状态
3.Thread.join(),wait(),park() 可以使的线程进入Waiting状态
3.2 如何终止线程
答:1.Thread.stop 强制终止线程,会使执行中断,不推荐
2.Thread.currentThread.isInterupted(),推荐使用,发送信号终止执行
3.3 synchronized实现原理是什么?
答:1.synchronized是java 关键字实现对 对象/方法上加锁
2.底层是由JMM自己实现的
3.JMM底层是对Object对象头上 存储字段锁标记位进行修改来实现,由MonitorEnter 加锁/MonitorExit 释放锁实现
3.4 Lock实现原理是什么?公平锁与非公平锁区别
答:1.Lock 底层是由AQS实现.设计思路包括 1.抢锁 2.CAS修改共享内存 3.挂起抢锁失败线程,AQS链表存储失败线程 4.唤醒挂起线程,继续执行操作
2.如何抢锁?-抢锁是通过CAS修改共享变量state 0-1实现抢锁
3.抢锁失败如何处理?---未抢占到锁线程,通过park()方法挂起线程,挂起的线程会存储到AQS的双向链表队列。
4.如何唤醒等待线程? RUNING线程执行结束 会调用unlock方法 unlock会通过unpark()方法会将链表中线程唤醒