题目来自于网络,答案是笔者整理的。仅供参考,欢迎指正
一、Java相关
-
Arraylist与LinkedList默认空间是多少;
-
Arraylist与LinkedList区别与各自的优势List 和 Map 区别;
-
谈谈HashMap,哈希表解决hash冲突的方法;
-
为什么要重写hashcode()和equals()以及他们之间的区别与关系;
-
Object的hashcode()是怎么计算的?
-
若hashcode方法永远返回1或者一个常量会产生什么结果?
-
Java Collections和Arrays的sort方法默认的排序方法是什么;
-
引用计数法与GC Root可达性分析法区别;
-
浅拷贝和深拷贝的区别;
-
String s="abc"和String s=new String("abc")区别;
-
HashSet方法里面的hashcode存在哪,如果重写equals不重写hashcode会怎么样?
-
反射的作用与实现原理;
-
Java中的回调机制;
-
模板方法模式;
-
开闭原则说一下;
-
发布/订阅使用场景;
-
KMP算法(一种改进的字符串匹配算法);
-
JMM里边的原子性、可见性、有序性是如何体现出来的,JMM中内存屏障是什么意思,
二、多线程
-
AtomicInteger底层实现原理;
-
synchronized与ReentraLock哪个是公平锁;
-
CAS机制会出现什么问题;
-
用过并发包下边的哪些类;
-
一个线程连着调用start两次会出现什么情况?
-
wait方法能不能被重写,wait能不能被中断;
-
线程池的实现?四种线程池?重要参数及原理?任务拒接策略有哪几种?
-
线程状态以及API怎么操作会发生这种转换;
-
常用的避免死锁方法;
三、JVM
-
Minor GC与Full GC分别在什么时候发生?什么时候触发Full GC;
-
GC收集器有哪些?CMS收集器与G1收集器的特点。
-
Java在什么时候会出现内存泄漏;
-
Java中的大对象如何进行存储;
-
rt.jar被什么类加载器加载,什么时间加载;
-
自己写的类被什么加载,什么时间加载;
-
自己写的两个不同的类是被同一个类加载器加载的吗?为什么?
-
为什么新生代内存需要有两个Survivor区?
-
几种常用的内存调试工具:jmap、jstack、jconsole;
-
类加载的五个过程:加载、验证、准备、解析、初始化;
-
G1停顿吗,CMS回收步骤,CMS为什么会停顿,停顿时间;
-
栈主要存的数据是什么,堆呢?
-
堆分为哪几块,比如说新生代老生代,那么新生代又分为什么?
-
软引用和弱引用的使用场景(软引用可以实现缓存,弱引用可以用来在回调函数中防止内存泄露);
四、数据库
-
数据库索引,什么是全文索引,全文索引中的倒排索引是什么原理;
-
数据库最佳左前缀原则是什么?
-
数据库的三大范式;
-
悲观锁和乐观锁的原理和应用场景;
-
左连接、右连接、内连接、外连接、交叉连接、笛卡儿积等;
-
一般情况下数据库宕机了如何进行恢复(什么是Write Ahead Log机制,什么是Double Write机制,什么是Check Point);
-
什么是redo日志、什么是undo日志;
-
数据库中的隔离性是怎样实现的;原子性、一致性、持久性又是如何实现的;
-
什么是组合索引,组合索引什么时候会失效;
-
关系型数据库和非关系型数据库区别;
-
数据库死锁如何解决;
-
MySQL并发情况下怎么解决(通过事务、隔离级别、锁);
-
MySQL中的MVCC机制是什么意思,根据具体场景,MVCC是否有问题;
-
MySQL数据库的隔离级别,以及如何解决幻读;
五、缓存服务器
-
Redis中zSet跳跃表问题;
-
Redis的set的应用场合?
-
Redis高级特性了解吗?
-
Redis的pipeline有什么用处?
-
Redis集群宕机如何处理,怎么样进行数据的迁移;
-
Redis的集群方案;
-
Redis原子操作怎么用比较好;
-
Redis过期策略是怎么实现的呢?
六、SSM相关
-
Spring中@Autowired和@Resource注解的区别?
-
Spring声明一个 bean 如何对其进行个性化定制;
-
MyBatis有什么优势;
-
MyBatis如何做事务管理;
七、操作系统
-
Linux静态链接和动态链接;
-
什么是IO多路复用模型(select、poll、epoll);
-
Linux中的grep管道用处?Linux的常用命令?
-
操作系统中虚拟地址、逻辑地址、线性地址、物理地址的概念及区别;
-
内存的页面置换算法;
-
内存的页面置换算法;
-
进程调度算法,操作系统是如何调度进程的;
-
父子进程、孤儿进程、僵死进程等概念;
-
fork进程时的操作;
-
kill用法,某个进程杀不掉的原因(僵死进程;进入内核态,忽略kill信号);
-
系统管理命令(如查看内存使用、网络情况);
-
find命令、awk使用;
-
Linux下排查某个死循环的线程;
八、网络相关
-
数据链路层是做什么的?
-
数据链路层的流量控制?
-
网络模型的分层、IP和Mac地址在那个层、TCP和HTTP分别在那个层;
-
TCP滑动窗口;
-
TCP为什么可靠;
-
TCP的同传,拆包与组装包是什么意思;
-
Https和Http有什么区别;
-
Http 为什么是无状态的;
-
TCP三次握手,为什么不是三次,为什么不是四次;
-
TCP的拥塞控制、流量控制详细说明?
-
Http1.0和Http2.0的区别;
-
两个不同ip地址的计算机之间如何通信;
-
地址解析协议ARP;
-
OSI七层模型分别对应着五层模型的哪一部分;
-
TCP三次握手数据丢失了怎么办?那如果后面又找到了呢?
九、分布式相关
-
消息队列使用的场景介绍和作用(应用耦合、异步消息、流量削锋等);
-
如何解决消息队列丢失消息和重复消费问题;
-
Kafka使用过吗,什么是幂等性?怎么保证一致性,持久化怎么做,分区partition的理解,LEO是什么意思,如何保证多个partition之间数据一致性的(ISR机制),为什么Kafka可以这么快(基于磁盘的顺序读写);
-
异步队列怎么实现;
-
你项目的并发是多少?怎么解决高并发问题?单机情况下Tomcat的并发大概是多少,MySQL的并发大致是多少?
-
什么是C10K问题;
-
高并发情况下怎么办;
-
分布式理论,什么是CAP理论,什么是Base理论,什么是Paxos理论;
-
分布式协议的选举算法;
-
说一下你对微服务的理解,与SOA的区别;
-
Dubbo的基本原理,RPC,支持哪些通信方式,服务的调用过程;
-
Dubbo如果有一个服务挂掉了怎么办;
-
分布式事务,操作两个表不在一个库,如何保证一致性。
-
分布式系统中,每台机器如何产生一个唯一的随机值;
-
系统的量级、pv、uv等;
-
什么是Hash一致性算法?分布式缓存的一致性,服务器如何扩容(哈希环);
-
正向代理、反向代理;
-
什么是客户端负载均衡策略、什么是服务器端负载均衡策略;
-
如何优化Tomcat,常见的优化方式有哪些;
-
Nginx的Master和Worker,Nginx是如何处理请求的;
十、系统设计相关
-
如何防止表单重复提交(Token令牌环等方式);
-
有一个url白名单,需要使用正则表达式进行过滤,但是url量级很大,大概亿级,那么如何优化正则表达式?如何优化亿级的url匹配呢?
-
常见的Nginx负载均衡策略;已有两台Nginx服务器了,倘若这时候再增加一台服务器,采用什么负载均衡算法比较好?
-
扫描二维码登录的过程解析;
-
如何设计一个生成唯一UUID的算法?
-
实现一个负载均衡的算法,服务器资源分配为70%、20%、10%;
-
有三个线程T1 T2 T3,如何保证他们按顺序执行;
-
三个线程循环输出ABCABCABC....
十一、安全相关
-
什么是XSS攻击,XSS攻击的一般表现形式有哪些?如何防止XSS攻击;
参考答案
Java相关
1.Arraylist与LinkedList默认空间是多少;
ArrayList:10
LinkedList:0
2.Arraylist与LinkedList区别与各自的优势
* 对于随机的访问,ArrayList优于LinkedList,因为LinkedList要移动指针
* 对于新增和删除操作,LinkedList占优势,因为ArrayList要移动数据
注意:在末尾添加一个元素的开销是相同的,主要是在内部新增删除开销不同
3.谈谈HashMap,哈希表解决hash冲突的方法
解决hash冲突的方法:
* 开放定址法(也称为再散列法,基本思想是:当关键字key的哈希地址p出现冲突时,以p为基础,产生另一个地址p1,如果p1仍然冲突,则再以p为基础,产生另一个地址p2..直到不再冲突)。主要有以下三种方法:
* 线性探测再散列(发生冲突时,顺序查看下一个单元,直到出现空单元)
* 二次探测再散列(发生冲突时,在表的左右跳跃式探测)
* 伪随机探测
* 再哈希法(同时构造多个不同的哈希函数,当某一个函数构造的哈希地址发生冲突时,再计算别的函数)
* 链地址法(将所有哈希地址为i的元素构成一个称为同义词链的单链表)适用于经常添加和删除的操作
* 建立公共溢出区(将哈希表分为基本表和溢出表,凡是和基本表冲突的,一律填入溢出区)
更多请参考:https://www.cnblogs.com/wuchaodzxx/p/7396599.html
4.为什么要重写hashcode()和equals()以及他们之间的区别与关系
我们的对象的hashCode和equals方法默认是调用Object对象的native类型的hashCode和equals方法的,这个比较的是两个对象的是否指向同一内存地址的。
但是有些时候我们希望,当对象的某些属性相同的时候就判定两个对象相等,那么这个时候我们就需要重写equals方法
那么为什么我们在重写equals方法后需要重写hashCode方法?
这就需要从集合类型说起了,HashSet不会存储相同的元素,这个相同就是比较两个元素的equals方法来决定的。HashSet实际就是使用HashMap实现的。
过程如下:当两个对象的hashCode相等的时候,就需要存储在数组的同一个索引处,然后再与索引处的链表元素进行逐个使用equals方法比较,如果相同,则重置当前元素,如果不相同,则添加到链表头。
重写equals方法不重写hashCode带来的隐患?
我们hashCode还是用Object.hashCode方法,equals方法一直返回false,这样两个指向同一内存地址的对象也是可以放入HashSet的
5.Object的hashcode()是怎么计算的?
public int hashCode() {
int lockWord = shadow$_monitor_;
final int lockWordStateMask = 0xC0000000; // Top 2 bits.
final int lockWordStateHash = 0x80000000; // Top 2 bits are value 2 (kStateHash).
final int lockWordHashMask = 0x0FFFFFFF; // Low 28 bits.
if ((lockWord & lockWordStateMask) == lockWordStateHash) {
return lockWord & lockWordHashMask;
}
return System.identityHashCode(this);
}
6.若hashcode方法永远返回1或者一个常量会产生什么结果?
HashMap集合就会变成一个链表结构的
7.Java Collections和Arrays的sort方法默认的排序方法是什么
可参考:https://blog.csdn.net/timheath/article/details/68930482
8.引用计数法与GC Root可达性分析法区别
引入计数法不能解决互相引用的问题
GCRoot可达性分析的方法可以解决(通过一系列的GCRoot的对象作为起始点,从这些根节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GCRoot没有任何引用链时,则证明此对象是不可用的)
9.浅拷贝和深拷贝的区别
浅拷贝:只拷贝对象的基本类型,对象类型则直接引用原对象地址
深拷贝:针对于浅拷贝中的对象类型,创建一份新的对象,指向新地址
如何重写深拷贝:对象实现cloneable接口;重写clone方法;clone方法将类的非基本类型的成员变量也同步使用clone方法来重新创建
10.String s="abc"和String s=new String("abc")区别
String有常量池的概念,String s = "abc",则会先去常量池去查询,如果有,则直接拿来使用;如果没有,则创建一个新的,并放回常量池;
new String("abc")不会去常量池查询,直接创建一个新的对象,貌似没有放入常量池
11.HashSet方法里面的hashcode存在哪,如果重写equals不重写hashcode会怎么样
答案同4
12.反射的作用与实现原理
1)什么是反射?
* 在运行状态中,对于任意一个类,都能够知道这个类的属性和方法
* 对于任意一个对象,都能够调用它的任何方法和属性
这种动态获取信息以及动态调用方法的功能称为java的反射
2)反射的作用?
在java中,只要给定类的全限定名,就可以通过反射机制获取类的全部信息,可以动态的创建对象和编译
3)反射的原理?
java文件编译之后会生成一个.class文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性等
反射主要通过:Class、Construcotr、Field、Method
13.Java中的回调机制
模块之间的调用分为几种类型:
* 同步调用
* 异步调用(可使用Future+Callback的方式实现)
* 回调
回调的思想:
类A的a()方法调用B的b()方法
类B的b()方法执行完毕主动调用A的callback()方法
回调的核心就是:回调方将本身传递给调用方,这样调用方就可以在调用完毕之后告诉回调方它想要知道的信息。
具体可参考:http://www.importnew.com/24220.html
14.模板方法模式
定义一个操作中的算法框架,而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变算法的结构而重定义算法的特定步骤
15.开闭原则说一下
* 对扩展开放
* 对修改关闭
在程序需要拓展的时候,不去修改原有代码,实现一种热插拔的效果。多使用接口和抽象类,来增强程序的可扩展性
16.发布/订阅使用场景
* 应用于异步编程,替代传统回调
* 取代对象之间的硬编码调用,对象之间不再显式调用
17.KMP算法(一种改进的字符串匹配算法)
具体可参考:https://www.cnblogs.com/yjiyjige/p/3263858.html
18.JMM里边的原子性、可见性、有序性是如何体现出来的,JMM中内存屏障是什么意思
原子性:java中提供两个高级的字节码指令monitorenter、monitorexit,使用对应的关键字synchronized来保证代码块内的操作是原子性的
可见性:java中使用volatile来保证多线程操作变量的可见性。volatile修饰的变量在修改后会被立刻同步到主内存,该变量每次使用之前都会从主内存中刷新
有序性:java中使用synchronized和volatile来实现有序性,只是显示方式有所区别。volatile禁止指令重排,synchronized保证同一时刻只允许一个线程操作
具体可参考:https://blog.csdn.net/lx_Frolf/article/details/82686201
二、多线程
1.AtomicInteger底层实现原理
CAS(compare and swap),是一种乐观锁技术,多个线程尝试使用CAS更新一个数据时,只有一个能够成功,其他线程都失败,失败的线程并不会被挂起,而是被告知这次竞争失败,并可以再次尝试。仅当预期值与内存值一致时,才修改内存值,否则什么都不做
2.synchronized与ReentraLock哪个是公平锁
synchronized是非公平锁
ReentrantLock默认是非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
3.CAS机制会出现什么问题
ABA问题:就是将值修改为B之后再改为A,那我们再比较的时候发现还是A,则判定值没有被修改,实际已经被改过一次了。
解决方案:AtomicStampedReference(有一个int值作为版本号,修改后会将版本号+1)、AtomicMarkableReference(使用一个boolean值作为是否更改的标志)
4.用过并发包下边的哪些类
线程池相关:Executors、ThreadPoolExecutor、FutureTask
容器相关:ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet、ArrayBlockingQueue
原子类相关:AtomicInteger、AtomicIntegerArray、AtomicLong、AtomicLongArray、AtomicReference
5.一个线程连着调用start两次会出现什么情况
报错如下:
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at javacore.mulit.MyThread.main(MyThread.java:40)
源码如下:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
第一次调用start之后,threadStatus会改变(非0,0代表新建),所以第二次在调用会报错
6.wait方法能不能被重写,wait能不能被中断
Object.wait()源码如下
public final void wait(long timeout, int nanos) throws InterruptedException {
可以看到,wait方法是final类型的,所以不能重写;
wait方法抛出InterruptedException,所以可以被中断,我们需要主动捕获这个异常
7.线程池的实现?四种线程池?重要参数及原理?任务拒接策略有哪几种
更多可参考:基础篇中的 讲讲线程池的实现原理 问题解答
重要参数:corePoolSize、maxPoolSize
原理:当线程池的线程数小于corePoolSize时,每来一个任务创建一个新的线程来执行;当线程数等于corePoolSize时,再来任务时会添加到workQueue中;当workQueue填满之后,会继续创建新的线程来执行任务,一直到线程数等于maxPoolSize;当线程数为maxPoolSize时,如果再来任务则执行拒绝策略。
8.线程状态以及API怎么操作会发生这种转换
生命周期:new/runnable/running/blocked/dead
9.常用的避免死锁方法
* 避免一个线程获取多个锁
* 尝试使用定时锁,使用ReentrantLock.lockInterrupt()/tryLock()
* 对于数据库锁,加锁和解锁必须在同一个数据库连接中,否则出现解锁失败的情况
三、JVM
1.Minor GC与Full GC分别在什么时候发生?什么时候触发Full GC
Minor GC:年轻代无法继续分配对象的时候发生(较频繁,回收速度较快)
Full GC:老年代无法继续分配对象的时候发生;当发生Minor GC的时候可能触发FullGC(因为老年代要为年轻代进行担保,由于进行一次垃圾回收之前无法确认还有多少对象存活,所以老年代并不清楚自己要担保多少空间,此时老年代会采用动态估算的方法:也就是上一次回收发送时晋升到老年代的对象容量的平均值作为经验值,这样就会有一个问题,当发生一次MinorGC以后,存活的对象剧增,此时老年代并没有满,但是此时平均值增加了,会造成FullGC)
2.GC收集器有哪些?CMS收集器与G1收集器的特点
垃圾回收算法一共有7个,3个属于年轻代、三个属于年老代,G1属于横跨年轻代和年老代的算法。JVM会从年轻代和年老代各选出一个算法进行组合,连线表示哪些算法可以组合使用
新生代的三个:使用的都是复制算法;回收时会导致stop the world;区别就是是否多线程回收;parallel Scavenge回收期更关注吞吐量(CPU运行代码的时间与CPU总消耗时间的比值),parallelScavenge提供参数用于精确控制吞吐量
老年代的三个:使用的标记-整理算法;
CMS是一种以获取最短回收停顿时间为目标的收集器,特点就是:并发收集、低停顿。
G1是一款面向服务端应用的垃圾收集器。特点就是:并行与并发、分代收集、空间整合、可预测的停顿。
CMS和G1的更多特点可关注:https://blog.csdn.net/linhu007/article/details/48897597
3.Java在什么时候会出现内存泄漏
内存泄漏:程序在申请内存后,无法释放已经申请的内存空间(当被分配的对象可达,但已无用,也就是未对废数据内存单元的引用置null即会引起内存泄漏)
内存溢出:程序申请内存时,没有足够的内存供使用
如何避免内存泄漏、溢出?
* 尽早释放无用对象的引用(在使用临时变量到时候,让引用变量在退出活动域后设置为null)
* 尽量少用静态变量(静态变量是全局的,GC不会回收)
* 避免集中创建对象,尤其是大对象
* 尽量运用对象池技术以提高系统性能
* 程序进行字符串处理时,尽量避免使用String,而应该使用StringBuilder
更多可参考:https://blog.csdn.net/sinat_35512245/article/details/54866068
4.Java中的大对象如何进行存储
新创建的对象一般放在Eden区;如果对象超过一定的阈值,则直接放到老年代
5.rt.jar被什么类加载器加载,什么时间加载
rt.jar被BootStrap加载器加载
在应用启动时加载?// TODO
6.自己写的类被什么加载,什么时间加载
AppClassLoader
7.自己写的两个不同的类是被同一个类加载器加载的吗?为什么?
是的,APPClassLoader
8.为什么新生代内存需要有两个Survivor区?
由于新生代对象朝生夕灭、存活对象少的特点,所以它的的GC方式是复制-清除方式,将存活的对象一次性拷贝到其中一个空的survivor区,Eden和另一个survivor区全部清空
9.几种常用的内存调试工具:jmap、jstack、jconsole
10.类加载的五个过程:加载、验证、准备、解析、初始化
加载:将class文件加载到JVM
验证:保证class文件包含的内容都是符合虚拟机规范的,并不会危害虚拟机
准备:为类变量分配内存并设置初始值
解析:将常量池中的符号引用转换为直接引用
初始化:真正开始执行类中定义的java程序代码。根据我们通过程序指定的主观计划去初始化类变量和其他资源
使用:
卸载:
11.G1停顿吗,CMS回收步骤,CMS为什么会停顿,停顿时间
G1也会停顿
CMS回收步骤:初始标记、并发标记、重新标记、并发清除
CMS用两次短暂停来代替串行标记整理算法的长暂停。
12.栈主要存的数据是什么,堆呢?
栈:线程私有的,每个方法在执行的同时,会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息
堆:公共区域,几乎所有的对象实例都会在这里分配内存
13.堆分为哪几块,比如说新生代老生代,那么新生代又分为什么
14.软引用和弱引用的使用场景
软引用:实现对内存敏感的缓存,如果还有空闲空间就可以暂时保存缓存,当内存不足是清理掉
弱引用:被弱引用关联的对象,在垃圾回收时,如果这个对象只被弱引用关联,那么这个对象被回收掉
未完待续...