java面经查缺补漏之第一天(希望自己能坚持,消除焦虑的最好方法就是,面对焦虑,兄弟们,奥里给!!!!)

今年暑假就要找工作了,虽然才2月末,但是现在就要开始准备了,在此之前已经学习了很多的理论知识,进行了广度优先遍历,参考https://blog.csdn.net/qq_41901915/article/details/103672370(里面有很多java开发需要掌握的知识点)。但是,有些内容不知道该学习多深,所以,从今天起,打算看别人的面经来进行深度优先遍历,把别人面试遇到的问题学精,这样才好

从今天起,每天一道算法题,每天一些面经题进行查缺补漏,希望自己能利用好这段疫情在家的时间,充实自己!写博客的目的就是第一是为了督促自己,第二是为了自己能有一个移动的笔记本,闲暇的时候不是拿出手机看抖音什么的,而是打开CSDN看看自己的博客。第三,也是为了分享,共勉,共同努力,如有错误,请指出,另外,这些题可能对初学者不太友好,需继续努力啊啊啊啊啊

先来几道题题,小试牛刀。

1.http协议2.0和1.1的区别?

(1)新的传输格式:2.0使用二进制格式,1.0依然使用基于文本格式。
(2)多路复用:连接共享,不同的request可以使用同一个连接传输(最后根据每个request上的id号组合成正常的请求)。
(3)header压缩:由于1.X中header带有大量的信息,并且得重复传输,2.0使用encoder来减少需要传输的hearder大小。

2.什么时候发生stackoverflow,一个线程的工作栈是多大,哪些区域会发生OOM(out of memory)?

按照JVM规范,JAVA虚拟机在运行时会管理以下的内存区域:java虚拟机栈,本地方法栈,java堆,方法区,运行时常量池,直接内存,程序计数器。按照JVM规范,除了程序计数器不会抛出OOM外,其他各个内存区域都可能会抛出OOM。

当虚拟机栈和本地方法栈不够用的时候,会发生stackoverflow,一个线程的工作栈的大小是可以设定的。可以通过虚拟机参数-Xss来设置栈的大小。

3.优先队列的实现,怎么实现排序?

程序员小灰那里有二叉堆,堆排序还有优先队列。

4.hashmap的实现,怎么解决冲突,其他解决冲突的方法,使用过哪些线程安全的集合?

hashmap是利用拉链法散列表来实现的,利用拉链来解决冲突,当哈希值相同的时候,在同一索引位置形成一个链表。

线程安全的集合又vector,hashtable,stack,enumeration。

5.treemap的实现,红黑树的优点,介绍一下其他的平衡树,数据库索引为什么采用B+树?

treemap是基于红黑树实现的,数据库索引是基于B+树实现的。

红黑树是牺牲了严格的高度平衡的优越条件为 代价红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。

红黑树也可以实现索引,但文件系统和数据库普遍使用B+树作为索引主要有两个原因

(1)更少的查找次数

(2)利用了磁盘的预读特性

(3)B+树支持范围查找

6.hashmap和treemap的时间复杂度?

HashMap的时间复杂度O(1),但是如果冲突较多,链表的时间复杂度是O(n),所以在JDK1.8 以后,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间,红黑树的时间复杂度是O(log n)。 所以查询一个HashMap数据的时间为 O(1) + O(n)或O(1) + O(log n)

TreeMap是基于红黑树实现的一个保证有序性的Map 基于红黑树,所以TreeMap的时间复杂度是O(log n),如果需要有排序的数据,直接存放进TreeMap中就行,TreeMap自己会给排序,不需要再写排序代码。

7.什么是消息队列?

参考:https://blog.csdn.net/yue_2018/article/details/89305275

把数据放到消息队列中的叫生产者,从消息队列中取数据的叫消费者。

消息队列的好处:

(1)解耦:比如BCD从A这里拿东西,如果A跑了,BCD全挂了。现在就是在中间放一个消息队列,A是生产者往消息队列中放数据,BCD从消息队列中拿数据,就算A跑了,仍然有消息队列存在,使得A与BCD之间没有了直接关系。

(2)异步:异步可以提升效率。比如A做一个产品50ms,BCD消费一个产品300ms。然后A先给B,再给C,再给D,那就是950ms。但是如果A把生产的东西放到消息队列中,150ms就可以产生三个,BCD可以分别直接用,让他们自己做自己的事,也就是异步了。

(3)削峰:比如BC各能处理1000,但此时来了3000,那么系统就崩溃了。如果加入消息队列,作为一个缓冲,那么就不会使得BC崩溃。

消息队列需要考虑的问题:

(1)高可用,如果消息队列挂掉了怎么办,所以需要一些集群和分布式的保障作用。

(2)数据丢失问题,也就是持久化问题将数据如何存储起来。

8.java中的并发,synchronzie关键字的作用,修饰方法,静态方法和类的区别。

(1)修饰一个类:作用的是这个类的所有对象

class ClassName {
   public void method() {
      synchronized(ClassName.class) {
         // todo
      }
   }
}

(2)修饰一个方法:作用的是调用这个方法的对象

public synchronized void method()
{
   // todo
}

(3)修饰一个静态的方法:作用的是这个类的所有对象;我们知道 静态方法是属于类的而不属于对象的 。同样的, synchronized修饰的静态方法锁定的是这个类的所有对象 。

public synchronized static void method() {
   // todo
}

9.java集合类,list,arraylist的实现,初始空间不够用如何扩容?

创建一个集合时,集合的初始容量为0,在第一次添加元素的时候,会对集合进行扩容,扩容之后,集合容量为10;之后,当向集合中添加元素达到集合的上限(也就是minCapacity大于elementData.length)时,会对集合再次扩容,扩容为原来的3/2。

10.jvm中的类的加载?

类加载过程主要分为7个过程,加载,验证,准备,解析,初始化,使用,卸载。其中比较重要的是加载,验证,准备,和解析阶段。

(1)加载

通过一个类的全限定名来获取二进制流,可以从class文件获取,可以从zip中获取,可以从网络中获取,这也是类加载过程可控性最强的一个部分。

(2)验证

主要就是验证这个二进制流是否符合java虚拟机的要求。

(3)准备

正式为static变量分配内存。在内存中生成一个代表这个类的对象,作为这个类各种数据的访问入口。

(4)解析

虚拟机将常量池内的符号引用替换为直接引用的过程。简单来说就是符号引用是间接指向内存,直接引用是直接指向内存。符号引用也是java一次编译到处运行的一个基础。

11.hashmap为什么是线程不安全的?

HashMap底层是一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。

主要表现在三个方面:

(1)添加

现在假如A线程和B线程同时对同一个数组位置进行添加操作,两个线程会同时得到现在的头结点,然后A写入新的头结点之后,B也写入新的头结点,那B的写入操作就会覆盖A的写入操作造成A的写入操作丢失。

(2)删除

和添加操作一样,大同小异,也是B的删除操作会覆盖A的删除操作,导致A的删除操作混乱。

(3)扩容

当加入新的键值对后键值对总数量超过门限值的时候会发生扩容操作。各自生成新的数组并rehash后赋给该map底层的数组table,结果最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。

12.什么时候触发minorGC?fullGC?

在这里我们介绍三层判断

第一层,判断老年代最大的可用连续空间是否大于新生代的所有对象总空间

大于,直接进行minorGC

小于,进行第二层判断,是否开启HandlerPromotionFailure

没有开启,直接进行fullGC

开启,进行第三层判断,判断老年代的最大连续内存空间是否大于历次晋升的大小

小于fullGC

大于minorGC

发布了481 篇原创文章 · 获赞 502 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/qq_41901915/article/details/104417110
今日推荐