-
java面试重点总结
面试题汇总
1、Java的SDK起到的作用
答:SDK:软件开发工具包(Software Development Kit) 包含JDK同时肯定包含JRE。
2、进程和线程的区别
答:线程在进程下运行,一个进程可以包含多个线程,就比如一个银行门店,开始营业,就是进程开启,然后每个窗口就是处理业务,每个窗口就是线程。
3、进程切换会发生什么
答:进程的切换,实质上就是被中断运行进程与待运行进程的上下文切换,分为两步:1、切换新得页表,然后使用新得虚拟地址空间。2、切换内核栈,加入新得内容(PCB控制块,资源相关),硬件剩下问切换。
4、进程调度算法
答:
批处理:
- 先来先服务算法,根据进程到达时间,严格按照顺序进行执行。
- 短任务优先算法,在排队的时候,把处理时间短的进程排在队列前面。
- 高相应比优先算法,公式:相应比=(等待时间+要求服务时间)/要求服务时间;相应比高的算法会先执行。
并发:
- 时间片轮转算法:每个进程轮流使用CPU资源,如果运行时间结束,就阻塞进程,切换下一个进程
- 优先级调度算法:每个进程设置一个优先级,运行时根据优先级的大小来进行调度,先调度最大优先级的进程。
5、TCP、UDP区别
答:TCP在连接前,通过三次握手来建立连接,而UDP没有握手机制;TCP对系统资源要求更多;UDP程序结构相对简单;TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证
tcp协议和udp协议的差别
TCP UDP
是否连接 面向连接 面向非连接
传输可靠性 可靠 不可靠
应用场合 少量数据 传输大量数据
速度 慢 快
6、java锁,关键字区别
答:synchronized关键字和java.util.concurrent.lock.Lock类
- 实现层面不一样。synchronized 是 Java 关键字,JVM层面 实现加锁和释放锁;Lock 是一个接口,在代码层面实现加锁和释放锁
- 是否自动释放锁。synchronized 在线程代码执行完或出现异常时自动释放锁;Lock 不会自动释放锁,需要在 finally {} 代码块显式地中释放锁
- 是否一直等待。synchronized 会导致线程拿不到锁一直等待;Lock 可以设置尝试获取锁或者获取锁失败一定时间超时
- 获取锁成功是否可知。synchronized 无法得知是否获取锁成功;Lock 可以通过 tryLock 获得加锁是否成功
- 功能复杂性。synchronized 加锁可重入、不可中断、非公平;Lock 可重入、可判断、可公平和不公平、细分读写锁提高效率
7、公平锁、非公平锁
答:公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能拿到锁。优点:所有的线程都能得到资源,不会饿死在队列中。缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。
非公平锁:多个线程去获取锁时,会直接尝试获取,获取不到,再进入等待序列,如果能获取,就直接获取。优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。缺点:你们可能也发现了,这样可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死。
8、springmvc和springboot的区别
答:springmvc是基于spring的ioc和aop开发的web框架,springboot只是在此基础上简化了springmvc的配置,通过一系列starter,降低了项目搭建的复杂度。
9、spring 的AOP用的什么设计模式:代理模式
三次握手、四次挥手
连接:三次握手;关闭:四次挥手
seq:序列号 :用来标记数据段的顺序
ack:确认号
ACK:ACK=1时确认号才有效
SYN=1:请求建立连接(三次握手)
FIN=1:请求断开连接(四次挥手)
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
个人总结理解记忆:
客户端:我要给你发快递了(第一次握手)
服务器:好的,我晓得了(第二次握手)
客户端:ok(我晓得你晓得了)(第三次握手)
四次挥手:
1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
个人理解:
客户端:我们分手吧!!(第一次挥手)
服务器:要的我晓得了,我把你的东西全部寄给你(第二次挥手)
服务器:东西老子寄完了,你可以滚了(第三次)
客户端:好的,不要再见了!(第四次)
为什么是四次挥手不是三次挥手:
在第一次挥手中,客户端提出断开要求,但服务器可能还有数据要发送(第二次挥手),然后服务端还需要告诉客户端我信息发完了(第三次挥手),最后客户端要回复服务端说知道了
GC 垃圾回收
GCRoots
- 虚拟机栈中本地变量表中引用的对象
- 方法区中静态属性引用的变量
- 方法区中常量引用的对象
- 本地方法栈中引用的对象
算法:
-
标记清除:将要回收的资源进行标记,然后清除掉
- 缺点:容易造成碎片,因为清理的资源再内存中是分散的,所以清除过后就缺一块少一块的,所以就会产生大量的碎片
- 标记整理:标记存活的对象,将存活的对象标记全部放入内存的一端
- 复制整理:把空间分成两块,每次只对其中一块进行 GC。当这块内存使用完时,就将还存活的对象复制到另一块上面。
MinorGC:复制算法
1:eden、servicorFrom 复制到 ServicorTo,年龄+1 首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年 龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不 够位置了就放到老年区); 2:清空 eden、servicorFrom 然后,清空 Eden 和 ServicorFrom 中的对象;
3:ServicorTo 和 ServicorFrom 互换 最后,ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom 区。
MajorGC :标记清除算法
首先扫描一次所有老年代,标记出存活的对象,然后回收没 有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减 少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的 时候,就会抛出 OOM(Out of Memory)异常。
在 Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间 的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用 本地内存。
默认情况下年龄到达 15 的对象会被 移到老生代中。
Http
状态码:
200:一切正常
400:客户端的问题
500:服务器问题
404:资源找不到
http请求步骤:
- 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
- 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
- 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
- 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
- 释放 TCP连接;
- 浏览器将该 html 文本并显示内容;
CAS
CAS:乐观锁的一种实现,通过unsafe提供硬件级别的原子操作,在更改数据时查看数据是否与之前相等,相等则更改。
ABA问题:三个线程初始值为A,第一个修改为B,第二个进入了,第三个抢先修改回A,然后第二个线程比对的时候发现没有问题,就继续修改。参考儿子去取钱,余额100,取50,然后发送了两次请求,第一次扣除了50,他妈给他转了50,然后第二个请求以为钱没变,就继续扣50。
解决办法:设置版本号
AQS:AQS(AbstractQueuedSynchronizer
),AQS是JDK下提供的一套用于实现基于FIFO等待队列的阻塞锁和相关的同步器的一个同步框架。这个抽象类被设计为作为一些可用原子int值来表示状态的同步器的基类。如果你有看过类似 CountDownLatch
类的源码实现,会发现其内部有一个继承了 AbstractQueuedSynchronizer
的内部类 Sync
。可见 CountDownLatch
是基于AQS框架来实现的一个同步器.类似的同步器在JUC下还有不少。(eg. Semaphore
)
数据库范式
数据库设计三大范式 - Ruthless - 博客园 (cnblogs.com)
第一范式:确保每列保持原子性:就是每个属性不能再进行分解。
就比如说地址还可以分为省、区、门牌,那么地址就不满足第一范式。
第二范式:再第一范式的基础上,表中每列必须跟主键相关,就是商品表就只有商品信息,没有其他关联信息(主要针对联合主键)
第三范式:在第二范式的基础上,确保每列和主键直接相关,而不是间接相关,非主键之间不能有依赖关系
类加载机制
- (1)加载:java类运行时候会生成一个class字节码文件,加载的过程就是去我们的操作系统寻找这个class文件。
-
(2)链接:这个过程就是把class文件加载到java虚拟机。
- 校验:校验字节码文件的合法性
- 准备:为静态资源准备内存空间
- 解析:将对象地址解析为真实地址
- (3)初始化:在虚拟机中根据class文件进行初始化。
- (4)使用:这个过程大家都明白。
- (5)卸载:使用完了,java虚拟机进行清理。
(1)class.forName() 除了将类的.class文件加载到 jvm 中之外,还会对类进行解释,执行类中的 static 块。当然还可以指定是否执行静态块。
(2)classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
双亲委派
面试官:java双亲委派机制及作用 - 简书 (jianshu.com)
Session和Cookie
Cookie是保存在浏览器上的一些数据,一般通过HTTP响应头set cookie来设置,当然也可以通过JS脚本来直接设置,Cookie是按照网站来进行组织和保存的,每一个网站都可以在浏览器中保存一些Cookie,保存好了之后,浏览器向这个网站发出的请求都会携带这些Cookie,然后后台就可以分析这些Cookie。
Session这个单词在不同的语境下可以有不同的含义。
它可以理解为一个抽象概念,即会话,会话用于记录一个用户在我们网站上的一些行为、一些状态,可以理解为一个上下文,Context。这些用户状态可以利用Cookie直接保存在前端,也可以保存在后台,然后利用Cookie中的Session ID来标识。
在另外的一些语境下,Session又可以指在后台保存用户状态来实现会话的方式,它把用户状态存储在后台的内存、数据库等介质中,然后我们利用请求的Cookie中保存的Session ID来为这个请求找到它对应的会话。
Session在一些语境下还可能专指后台保存的用户状态
cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
出处:
https://www.cnblogs.com/gscicode/p/15079735.html