Java 后端开发面试题目总结(更新中~~~)(题目来源于牛客各路大神分享的面试及个人面试总结~~)

(能力有限,从面试的角度你问我答,欢迎大家评论补充,纠正~~~)

一、Java基础相关

1.java的Map里面优秀的设计

1.首当其冲的就应该是HashMap的扩容机制,jdk8之后,hashmap采用数组+链表+红黑树的结构,链表转红黑树避免了当数据量大的时候,链表过长导致时间复杂度高的问题。 2.转换阈值的设计,包括链表转红黑树,数组超过长度*0.75 的时候,就要通过复制的方式进行扩容。 3.hash 算法的优化,hash算法是经过hash函数计算后,在高低位进行异或得出的,增加了hash的散列性,同时也避免了长度的越界。 4.ConcurrentHashMap 的锁机制使用的是Segment段,ConcurrentHashMap由Segment段组成,对每一个Segment段加锁,就相当于对全局加锁,jdk1.8 的concurrentHashMap的锁机制使用的是synchronized机制,并且在put 元素的时候进行初始化,这个过程的设计没有使用锁机制,但是依旧保证了安全性,采用CAS 自旋的形式保证了安全性。

2.Semaphore,CountDownLatch,CyclicBarrier 区别(留下了没有技术含量的眼泪~~)(Semaphore 可以acquire和release,CountDownLatch 设置一个屏障,前置任务完成才会执行这个任务,CyclicBarrier 可以重置屏障)

3.讲一下Hashmap 的底层实现

答:(还真不知道该从何说起,也不知道说到什么程度算可以了)先说说HashMap的底层数据结构吧,在1.7之前是 由数组+链表组成,在1.8后底层数据结构变为了数组+链表+红黑树的结构。每一个桶位的元素是一个Node节点,主要有hash 值,实际的key 值,value 值以及指向下一个节点的next 指针,hashmap的默认初始容量为16,当我们自定义容量的时候会将容量设置为大于你设置数值的最小2的幂。如果出现hash冲突,就会采用拉链法在该桶位后面进行尾查法插入元素,当链表的长度大于8的时候并且数组的长度大于等于64的时候,就会出现链表转红黑树的操作,当容量小于6的时候,就会出现红黑树转链表的操作,否则如果数组的长度小于64,只会出现数组的扩容操作,该操作是通过复制的方式,rehash的方式进行扩容的。hashmap的扩容机制为当数组的长度大于 当前长度*负载因子的时候,就会出现扩容现象。

4.讲一下CurrentHashMap的底层实现

答:CurrentHashMap的底层实现是先从结构上说一下,CurrentHashMap1.7的时候使用的是Segment数组+HashEntry数组+链表的形式实现。每一个segment是一个类似于HashMap的结构,所以每一个HashMap的内部是可以扩容的,但是segment数组一旦初始化后便不可更改,默认大小为16,默认最多支持16个线程并发,segment内部使用的是ReentrantLock 的锁机制,不断的循环tryLock(),结点的插入使用的是头插法。而CurrentHashMap1.8 的实现使用的是Node数组+链表/红黑树的形式实现。并且concurrentHashMap的初始化是在put的时候进行的,在初始化的时候使用的是CAS自旋锁。通过sizeCtl这个变量控制的,该变量有四个值用来表示当前初始化的状态。

5. AQS原理及作用

答:(不了解~先将知道的说一下,后期还会在学习整理~)AQS的全称是AbstractQueenSynchronizer,也就是抽象队列同步器,用来构建锁还有同步器的,基本原理是当有新的线程过来访问,如果共享资源空闲可用的话,则当前线程获得锁,其他线程不能访问共享资源。当共享资源被其他线程占用,该线程就被阻塞并等待,因此,就需要一套阻塞与唤醒时锁的分配机制。这个机制AQS是使用CLH抽象队列锁实现的(虚拟的双向队列fifo)。AQS的资源访问分为共享资源访问与独占资源访问两种方式,CoundDownLatch 的实现就是基于共享资源的访问,Reentrantlock的实现就是基于独占的方式。

6.Executors有了解吗?

答:(不了解~先将知道的说一下,后期还会去学习整理~)只知道Executors这个类是在Java.utils.concurrent 包下的,主要是用来做线程池的创建,但是现在线程池创建一般不用这个,而是使用ThreadPoolExecutor的方式创建。

7.ArrayList和LinkedList的区别,哪个插入性能高,有存储上限吗

答:ArrayList与LinkedList的主要区别在于底层实现不同,前者基于数组,后者基于链表。因此,两者的特性主要是数组与链表的区别。插入上linkedlist的性能更高。有存储上限,受内存的限制(要不然还要数据库干啥~~)。

8.ArrayList扩容机制

答:ArrayList扩容机制,里面细节有点多,想要仔细了解的话,恐怕还得看源码。从面试角度,我认为可以这样回答,ArrayList的底层数据结构实际上使用的是数组,在扩容的时候是通过复制原有的数组进行扩容的,新数组的长度大约为原来数组的1.5倍。主要调用了两个函数一个是System.Arraycopy() 这是一个native 方法,作用是将新数组 从某一个位置开始到某一个位置结束的数据,复制到新数组中。Arrays.copyOf() 方法则是系统内部自己创建一个数组进行复制,其实底层还是调用了System.Arraycopy() 这个方法。

9.线程池的参数,原理,线程复用,拒绝策略

答:线程池的原理为:我们通常在启动线程的时候,使用的是 .start()方法进行启动的,.start()方法准备了线程启动的必要参数,实际在执行的时候,又调用的是 run()方法,我们可以集成重写Thread类,在其start 方法中添加不断循环调用传递过来的Runnable 对象,创建一个Queue队列,将n个处理线程存放到队列中去。需要线程的时候,就去线程池中去取。用完就放入队列后面。从而实现了线程池的创建,以及线程的重复使用。 参数: 核心线程数 任务队列长度 最大线程数量 keepAliveTime :当线程池中的线程数量大于核心线程数量的时候,线程池中的线程不会立即销毁,而是等待只有等待的时间超过了keepAliveTime的时候 才会被回收访问。 拒绝策略: 1.直接抛弃新提交的任务 DiscardPolicy 2.拒绝提交的任务并抛出异常 AbortPolicy 3.使用管理线程执行当前的任务 CallerRunsPolicy 4.丢弃最早提交的任务 DiscardOldestPolice

10.讲一讲java 的权限修饰符

访问权限   类   包  子类  其他包

public     ∨   ∨   ∨     ∨

protect    ∨   ∨   ∨     ×

default    ∨   ∨   ×     ×

private    ∨   ×   ×     ×

11.原子类的CAS是如何实现的?

12.RPC的原理,你是怎么理解的?

13.将一下synchronized 以及volatile 的区别

答:synchronized主要是用来保证多线程程序的同步性的,用来修饰代码块、方法(普通方法,静态方法)。 volatile主要用来修饰变量的。 synchronized 可以保证并发编程的原子性、顺序性、以及可见性。在实现方面比较繁琐。volatile 是synchronized的轻量级实现,主要是保证变量的可见性以及防止指令重排。

14.java的1.8 新特性

答:1.添加了流处理的方式,可以将集合转化为流进行处理。 2.添加了lambda表达式,对于有一个方法的接口,可以通过lambda表达式进行书写实现方法。 3.对接口进行了升级,包括添加了可以实现的默认方法,增加了静态方法,增量加了public 修饰的方法等。

15.什么是原子性

答:原子性就是一系列的操作看作一个原子单位,在执行的时候要么都成功,要么都失败。

16.讲一下什么是线程池

答:在使用多线程的时候,我们频繁的关闭处理线程需要耗费大量的资源,耗费不必要的时间。因此,我们通过池化的技术,将一些已经创建好的线程直接放在这个池子里面,使用的时候就拿出来,用完就放进去。从而避免了一些不必要的开销。(面试官不说停的话,可以继续讲 线程池的创建 Threadpoolexecuter 相关的内容,以及线程池相关的一些参数等内容)

17. 介绍一下JMM

答:JMM是java的内存模型,类似操作系统的内存模型,类似cpu 与 内存,高速缓存的关系。java的JMM模型分为三个层次以及8种操作,分别是主内存,本地内存,线程。每个线程拥有一个本地内存,当线程需要执行操作的时候,会先从主存加载数据到本地内存,然后线程直接与本地内存交互。分为8种操作:

  • read : 将数据从主存传递到本地内存
  • load :将数据保存到本地内存
  • write : 将数据从本地内存传递到主存
  • store : 将数据保存到主存
  • lock : 给主存上的数据加锁
  • unlock : 解锁主存上的数据
  • assign : 将cpu 执行完的数据传递到本地内存上
  • use : 线程使用本地内存上的数据

18. 类加载的时机

19. Mysql的事务如果执行过程中报错但是没有回滚如何解决

20.

二、Mysql

1.说说Mysql 的日志 bin log,redo log 和 undo log (emmmm~~~)

答:先说一下Mysql 读取数据与修改数据的过程,mysql的数据存储在磁盘中,当应用程序读取数据的时候,会首先将数据放到buffer pool 缓冲池中,读取数据是按页读取的,bufferpool中数据存储的基本单位也是页。当我们修改数据的时候,也是会首先修改buffer pool里面的数据,在修改数据的时候,就会生成redo log 日志,用来记录你修改操作的记录,当我们进行持久化的时候,也是会根据redo log 日志来进行持久化的操作。同时也会生成undo log日志,用来记录修改前的操作,在并发事务中,undo log是以版本链的形式进行记录的,当我们执行回滚操作的时候,就是根据undo log 日志进行回滚。undo log 在innodb 引擎下才有,对于myisam 是不支持事务的,因此没有undo log表,bin log 日志是基于mysql 本身的日志,与存储引擎并没有很大的关系,主要是用来支持mysql的分布式部署的,也是用来记录当前执行的操作,与redolog 一样。但是在进行主从复制的时候,主节点会将改日志发送给从节点。

2.说说mysql的索引

答:这一块我会从mysql的存储引擎开始聊起,mysql的存储引擎主要包括InnoDB,myISAM,memory三种,从数据结构上看这三个存储引擎的索引机制,其中InnoDB,myISAM 主要使用的是B+树,memory 主要使用的是hash 索引。如果按照功能分类的话 可以分为 唯一索引,联合索引(最左匹配原则),外键索引,主键索引,普通索引以及全文索引(InnoDB 5.6之后支持~~)。按存储方式分类的话,主要包括聚簇索引和非聚簇索引。非聚簇索引的叶子结点上 只会存储部分数据,聚簇索引的叶子节点上存储全部的数据。

3.下一个问题很显然的会来的,聊一聊b+树索引。为什么使用b+树索引,与b树索引的区别是什么?为什B+树比B树更加矮小?

答: 聊b+树索引的话,就先从索引开始说起,索引就是为了提高Mysql查询效率的有序的数据结构,没有索引的时候,我们需要遍历查找时间复杂度高,后来出现了二叉树索引,但是二叉树存在链化问题,因此又出现了红黑树,就是特殊的平衡二叉树,避免了链化问题,但是当数据量非常大的时候,查询效率依然不高,因此出现了b树,就是多叉树。这时候查询的效率明显提高了,但是b树的节点是存储真实数据的,真实数据是存储在磁盘上的,因此,我们在进行索引查找的时候,就避免不了与磁盘之间进行IO操作,磁盘之间的IO操作是非常耗费时间的,为了对此进行优化,引入了b+树索引,索引非叶子节点上是不存储真是数据的,只存储索引值,值的存储是以磁盘页为单位的,b+树由原来的b树存储真实数据,转为了存储索引,在磁盘空间一定的情况下,显然b+一页能存储的索引更多,因此也比b树更短小,除此之外,b+树的索引,存储到内存中,增加了查询速度,减少了io次数,b+树的叶子节点设置为双向链表的形式,也支持了范围查询。

4. 查询时候没启用索引的原因。

答:这时候肯定要看你查询的字段上面有没有设置索引呢! 然后在从自己的查询语句上进行分析索引失效的情况。使用like 的时候如果使用 ‘%c%’ 会导致索引失效;使用 in 关键字会导致索引失效;使用 is null 会导致索引失效;在有需要计算的sql 语句中where c/2 = 4 类似这种会导致索引失效;在使用联合索引的时候,如果违背了最左匹配原则 会导致索引失效,使用不等号、or等关键字 也会导致索引失效等情况。

5.left join 、right join 、 innor join 的区别

答: left join是以左表为基准进行查询,左表的字段全部显示,右表只显示与左表匹配的字段 right join是以右表为基准进行查询,右表的字段全部显示,左表只会显示匹配的字段 innor join是显示两个表相同的字段

6. mysql的数据类型

答; mysql的数据类型主要分为以下几个大的方面,数值类型(常用的主要有 int,biginteger,float,double);日期和时间类型(Data,time,datatime混合);字符串类型(char,varchar,text,longtext)等。

7. mysql 里面时间是怎么存储的?

(这个真不知道怎么回答~~) 答:mysql 里面的时间使用的是datatime 数据类型进行存储。最理想的存储日期信息的方法是使用MySQL 时间戳。为了获得服务器本地时区的当前时间,可以使用now或CURRENT_TIMESTAMP 函数,也可以使用UTC_TIMESTAMP 函数获得UTC 时区时间戳。

8. buffer pool 机制

答:这里先说一下buffer pool 机制的由来,就像是操作系统中内存的思想一样,程序直接访问物理内存需要的时间及性能开销是比较大的,程序处理速度较快,但是数据提供慢。因此为了解决这个问题,就引出了内存。 buffer pool 机制是在mysql 中类似内存的一个机制,数据库中的数据真实存储是在磁盘上的,但是程序处理速度较快,因此,就会预先将数据存储在buffer pool中,数据库中的数据的存储是以页为单位的,当执行数据读取的时候,会将数据同样以页的方式掉入到buffer pool 中,在buffer pool 中进行数据的读写。那么如何更快的知道哪一页被使用了?以及bufferpool 的内存是有限的,那么该如何进行内存管理呢? buffer pool 除了一页页的内存之外,还会维护三个链表,其中 free 链表用来记录空闲页的信息,当需要使用内存的时候,就从链表头部取出一个空白页进行使用。当某一个页的内容被清除的时候,就会在链表头部插入该页的信息。flush 链表,该链表用来记录你修改过的页,因此,当我们对数据进行持久化的时候,会通过读取flush链表的信息,对数据库中的页进行操作。lru链表是最近最少使用的淘汰机制,当某一个页被使用的时候,就会放到链表的头部,因此,当我们淘汰页的时候,可以从改链表的尾部开始淘汰。

9. Mysql语句的执行顺序

答:from -> where ->group by ->having ->select ->order by ->limit

10. 并发事务的底层mvcc 机制

答:Mvcc是保证RR和RC事务隔离的底层实现机制,RR只在第一次执行快照读的时候会生成ReadView表,RC会在每次执行快照读的时候都生成ReadView表,因此可重复读每次查询的都是同一张ReadView表格,RC每次查询的ReadView表格是不一样的。那么什么是ReadView表呢?ReadView表是用来记录当前活跃的事务id(即未提交事物)的链表,是快照读读取事务的依据。注意包含四个字段,m_ids(当前活跃事物的id集合),min_trx_id(最小活跃事物的编号),max_trx_id(最大活跃事物的编号+1),creator_trx_id(创建ReadView的事物的编号)。通过ReadView是如何实现RC的呢?首先查看当前事物的id 是不是与creator_trx_id相等,如果相等说明是自己创建的事务,可以访问。否则就看当前id(cur_id)与min_trx_id 的大小关系,如果cur_id <min_trx_id,则可以访问数据,说明该事物在活跃事物之前已经提交了数据,如果cur_id >max_trx_id,则说明该事务是在ReadView生成之后才开启的,不能访问。如果min_trx_id<cur_id <max_trx_id ,就查看在m_ids 中是否包含该id,如果包含该id则不允许访问。

11.有一条mysql查询很慢,你有什么优化手段,请讲一下

答:

三、Redis

1.Redis为什么不需要多线程

Redis是基于内存的数据库,多线程的出现是为了提高CPU的利用效率的,Redis的性能瓶颈在于网络I/O以及内存的大小,单线程编程更容易维护,多线程会出现死锁,线程上下文切换的问题,甚至会影响性能。

2.Redis 既然是单线程(Redis 后面的版本也有引入多线程了)那Redis 是如何监听大量的客户端连接的呢?

答:Redis使用的是Reactor的模式,通过I/O多路复用的程序来监听大量的客户端连接。

3. 上面这样回答,面试官肯定又会问,给我讲讲I/O多路复用模型吧~~~(此刻的我只想~~~~~~)

答:我们想让多个事务同时的执行,可以通过写一个多线程的方式进行,但是多线程创建的开销比较大,因此,就可以使用I/O多路复用模型,I/O多路复用模型的三个概念select、poll、epoll,拿Linux 系统来讲,每一个链接就是一个文件,对于windows系统,则是依靠DMA来实现的,先来看一下select ,select 就是在有链接到来的时候,会在用户态生成一个bitmap用来记录链接的情况,bitmap是有大小限制的(1024)。体现在程序上就是会开启一个while 循环一直监听用户态的bitmap,将bitmap 调入内核态进行判断,内核会将有数据的那位进行置位(也就是将有数据的文件进行标识),某一个位置是否有数据需要进行处理,处理完成后继续循环调入判断。select 每次都需重新创建bitmap,以及bitmap的大小是有限制的,用户态到内核态的转换需要更高的开销。 poll 的改进: 将select的bitmap 改为了结构体的存储,包含fd,events以及revents 三个字段,实现了结构体的重用,fd 用来记录文件描述符,events 用来记录是文件的读事件还是写事件,revents是用来表示置位的,例如我们判断某一个文件是否已经被使用,可以通过修改revents字段的值来表示,而不像bitmap 一样,直接整个值被修改了。 epoold的改进 则是将原来 内核态与用户态分开存储的结构体空间,改为了内核态与用户态共享的空间,减少 了用户态到内核态数据的copy.

4.Redis的过期策略

答:Redis的过期策略主要包括,volatile-least recently used,volatile-least frequency used,allkeys-lfu,allKey-least recently used,volatile-ttl(从设置了过期时间的值中选择将要过期的时间淘汰),volatile-random(从设置了过期时间的值中随机选择值进行淘汰),allkey-random(从所有数据中随机选择淘汰).

5.Redis的数据类型

答:主要包括5种基本类型string 通过key value的形式存储数据;set 存放不重复的集合;zset 存放不重复的集合、并且可以设置元素的权重,根据元素的权重排序;list 列表类型 存放无序的元素可以获取头部元素或者尾部元素,hash 类似于java的hashmap 这个值是一个hashmap集合以及 三种特殊类型 bitMap 只用0,1 表示,,Hyperloglog基数统计 计算集合中不重复的元素的个数,例如网页用户浏览量的计算。以及geospatial地理位置,通常可以用在地图计算相关。

6.Zset的底层数据结构

参考链接 这一块不是很懂,上面的参考链接讲解的挺详细的。如果我回答的话,我会按照下面逻辑回答。 答:Zset的底层实现包括ziplist和skiplist+dict的形式。其中ziplist中每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存值,第二个节点保存分值(就是你要排序的那个权重),在压缩链表内会使用从小到大的形式进行排序。对于skiplist+dict 的形式呢,dict是保存的一个键值对,就是值+分值,跳表的出现的原因是,我们想要实现一个插入、查找、删除都快的数据结构,对于我们基本的数据结构数组和链表,数组查找快,但是插入慢;链表查找慢但是删除快为O(1) ,那么该如何去解决这个问题呢?就需要在链表的基础上进行了优化,增加了log(n) 层,这log(n) 层,从下到上是依次稀疏的,但维护的还是一个链表。并且为了造成空间的浪费以及提高查询效率,会通过指针来共享相同元素的成员和分值。从而降低了查找时间复杂度变为了O(log(n)),但是导致了插入的时间复杂度也为O(log(n))。

7.redis的持久化策略

答:我们知道Redis是基于内存的一个数据库,数据并不会真实的保存到磁盘上,因此,当电脑关机,遇到断电等情况,就会导致数据的丢失。那么我们应该怎么解决这个问题呢?就是-持久化。redis 提供了两种持久化的策略,一种是AOF,一种是快照项的RDB。 AOP是保存我们执行过的插入和删除,创建表等的命令。在数据恢复的时候比较慢,我们可以通过在配置文件中配置aop的配置项来确定,多久保存一次命令,最低丢失一秒的命令。 RDB是定时保存我们在内存中的数据到.db 文件中,保存的是真实的数据,数据恢复比较快,而且还需要一个新的线程去监控这个过程,适用于对数据完整性不高的情况,会丢失一段时间的数据。

8.Redis的原子操作指令

答:Redis的事务应该是不保证原子操作的,我也不清楚这里的原子操作是不是🈯️实现事务,实现的事务的命令包括 Mutex,exec,monitor以及discard。如果不是事务的话,Redis其余的单命令操作应该也是原子的以及INCR/DECR/SETNX 将数据的读写以及判断合并成了一个单命令实现也是原子的。

9. redis中master 与slave异步同步的话,怎么判断slave同步进度?

四、计算机网络

1.GET和POST的区别

答:1.get主要功能是从服务器上获取数据,post 主要是向服务器上提交数据 2.get的参数形式主要是以url上进行传递,post 是以表单的形式进行提交,并且post能支持多种类型的数据格式。 3.get 传递的数据大小受浏览器的限制,post的数据大小是不受限制的。 4.get 方式需要使用 Request.QueryString 来取得变量的值,而 post 方式通过 Request.Form 来获取

2.HTTP3.0的优势,为什么使用UDP实现?主流再用的HTTP协议?HTTP2.0的优点?

答:http3.0 在传输层主要使用的是udp协议,udp的上层协议使用的是QUIC 协议,主要是为了保证安全性。为什么使用udp 作为传输层协议呢? 因为,tcp在当前大数据时代下有缺点,tcp主要在于需要三次握手,以及tcp为了保证数据可靠传输会有,将数据分段编号,并在接收端进行校验,拥塞控制机制(慢开始,快重传,快恢复,拥塞避免等),流量控制,ARQ协议,超时重传等机制。如果使用udp的话就会提高了传输速度,增加了用户体验。(但是udp不保证可靠传输,这个问题是怎么解决的呢?) 主流使用的http 协议主要还是1.*版本的。 http2 的优点,http1 都是使用字符串的形式进行数据的传输,http2 主要是使用二进制流的形式进行数据的传输。HTTP/2.0 支持多路复用。因为流 ID 的存在, 通过同一个 HTTP 请求可以实现多个 HTTP 请求传输,客户端和服务器可以通过流 ID 来标识究竟是哪个流从而定位到是哪个 HTTP 请求。

3.说一下输入url 整个浏览器发生了什么?

答:首先是url使用DNS进行域名解析,DNS域名解析会首先从本地域名服务器开始检查,如果本地有缓存记录,就直接返回,否则就会按照根域名,顶级域名,权威域名的顺序去查找对应的IP地址。查找到对应的IP地址后使用tcp进行三次握手的过程,客户端与服务器的端口建立链接,http1.0 使用的是80端口,1.1版本使用的是443端口,然后使用http 协议对客户端数据进行编码,在运输层会以数据报的形式进行传递,服务器端使用tcp 协议进行报文重组,根据http的请求进行不同的处理,将处理结果同样也利用TCP/IP协议进行回传,客户端接收到消息后进行页面解析与渲染,最后可视化呈现给用户。tcp通过四次挥手断开链接。

4.OSI七层模型

答:OSI 自底向上依次为 物理层,该层负责屏蔽掉物理介质的影响,实现比特流的透明传输。数据链路层,主机与主机之间数据的传输是在一段一段链路上进行数据传输的,比较有代表性的协议ARP协议就是该层协议。网络层,网络层主要负责如何选择一个传输数据的路径,主要的协议ip协议。运输层,是实现两个主机之间端到端链接,主要的协议包括tcp/udp。会话层,表示层,应用层,这三层协议可以归纳为都是应用层的协议。会话层就是负责建立、管理和终止表示层实体之间的通信会话。表示层是能够解释交换数据的含义,比如压缩文件,png,jpeg 等格式。应用层 定义了进程之间的交互规则,包含的协议主要包括DNS,http系列,smtp 等。

5.TCP和UDP的差别

答:TCP是面向连接的传输是以字符流的方式进行数据的传输,建立TCP的链接需要耗费更多的网络资源,包含三次握手建立连接,以及四次挥手断开🔗,数据的传输效率较低。 UDP是一个不需要确认是否连接成功的运输层协议,以数据报的形式进行数据的传输,传输数据的效率快,耗费的网络资源少。

6.TCP的粘包和拆包问题

答:学习链接 TCP的粘包和拆包问题是在tcp使用socket进行通信的时候出现的,tcp 是基于流的数据传输协议,应用层的包会被转化为流进行数据的传输,因此,当客户端发送了 多个数据包 组成了一个字符串在网络中进行传输,那么服务器端收到该流后,需要对这些字符串进行拆包。因为,数据包的长度不固定,因此就会给拆包带来困难。我们可以使用添加包头的方式,或者使用标准的应用层协议http、https 进行数据包的传递。

7.讲一下三次握手以及四次挥手断开链接

答:三次握手--首先,客户端处于关闭状态,服务器端处于listen 状态,客户端首先发起链接请求发送一个标识位 syn,客户端的状态转为SYN_SENT。该连接让服务器端确定了自己的接受正常,客户端的发送正常。当服务器端收到改标志位状态转为SYN_REC,服务器发送SYN,ACK。客户端接受到服务器发送的SYN,ACK,并发送ACK给服务器,客户端的状态转变为established。该过程让客户端确认了自己的发送接收正常,客户端的发送接收正常。当服务器端收到客户端的ack后也转变为established 状态,这时候服务器端也确定了自己的发送正常,客户端的接收正常,可以开始通信。(这也是为什么要三次握手) 图片说明 四次挥手断开链接-- 首先服务器端与客户端都在established 状态,这里以客户端首先向服务器端发起断开链接为例进行解释。客户端向服务器的数据传递完毕,首先发送一个FIN给服务器,表示自己的通信完成,然后转为FIN_wait1 阶段,当服务器端收到FIN的时候,就向客户端回复一个ACK ,服务器端就由established 状态转变为close_wait 阶段,客户端收到服务器端的ACK后就转变为FIN_wait2阶段。然后服务器端向客户端发送ACK+FIN,服务器端转变为last_ack状态,客户端收到服务器发送的消息后,在给服务器端回复一个ack,并转变为time_wait状态。经过2msl后客户端转变为close阶段,当服务器端收到客户端发送的ack后,转变为close阶段。 四次挥手

五、框架相关

1.springBoot 相比Spring的优点

答:首先明确springboot 与spring的关系,springboot是为了能够创建独立的生产级别的基于spring的应用程序。简单来说springboot 就是spring,那么springboot 相比spring 做了哪些改进呢?主要是简化了xml 的配置,内部集成了一些例如tomcat 之类的中间件,能让web 程序运行就像普通的java程序一样运行,Spring Boot 项目所需要的开发或者工程时间明显是减少的。

2.spring 如何解决循环依赖

3. spring 一、二、三级缓存都存放什么

4. spring 事务传播方式,介绍几种

  1. PROPAGATION_REQUIRED:提交了一个新的事务的时候,如果当前有事务就使用当前事务执行,否则就新建事务执行
  2. PROPAGATION_SUPPORTS:提交了一个新的事务的时候,如果当前有事务就使用当前事务执行,否则就按照非事务执行
  3. PROPAGATION_MANDATORY:提交了一个新的事务的时候,如果当前有事务就使用当前的事务执行,否则就抛出异常 4.PROPAGATION_NOT_REQUIRES_NEW: 提交了一个新的事务的时候,不管当前有没有事务,都创建新的事务执行 5.PROPAGATION_NOT_SUPPORTED:提交一个事务,按照非事务的方式执行,如果当前存在事务就将当前的事务挂起 。 6.PROPAGATION_NEVER : 以非事务的方式执行,如果当前存在事务,则抛出异常
  4. PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按照REQUIRED 执行。

5. springmvc 执行流程

答:springmvc的执行主要是包含以下几个组件,通过下面的组件相互协调运行。主要包含前端控制器,处理器映射器,处理器适配器,处理器,视图解析器,视图以上几个方面。 用户请求到达前端控制器,前端控制器将消息转给处理器映射器以获得处理器,处理器映射器返回处理器给处理器适配器,处理器适配器负责执行处理器中的相关内容,将处理结果反馈给前端控制器,前端控制器将消息在转发给视图解析器,视图解析器将结果解析生成视图。最后,将视图返回给前端控制器,然后将结果返回。

6.mybatis 一二级缓存,区别以及失效情况

7. 讲一下spring的AOP

答:spring的aop的含义是面向切面的编程,我们一般将程序代码中的公共逻辑部分抽取出来生成切面。当我们使用的时候在通过spring的通知配合切面表达式添加到代码中。 aop的底层实现原理是基于代理的技术,主要分为静态代理和动态代理。其中、静态代理指的是在程序编译器就会将增强代码编织进程序中。在程序运行期间不会改变。而动态代理技术分为基于JDK的动态代理以及CGLIB动态代理技术。动态代理会在运行时期产生一个新的临时对象。其中,基于JDK的动态代理技术要求增强类必须要实现接口。主要使用proxy,invocationhandl实现。CGLIB不需要增强类实现接口,主要是依靠继承的方式实现,在运行期间会生成一个子类对象。因此,如果一个类被标记为final 是无法使用cglib做动态代理的。

8. 讲一下spring的IOC

答:我对IOC的理解在于ioc就是控制反转,以前我们创建对象是由自己把控的。现在,这种权利转移到了spring的容器中,并由容器根据配置文件去创建和管理各个实例,以及各个实例之间的关系。控制反转的实现主要是基于java的反射机制。

9. 讲一下restful风格

六、操作系统相关

1. 进程和线程的区别

答:进程相当于程序的一次执行,线程是程序执行的最小单位,一个进程包含多个线程,线程之间可以共享数据运行。进程之间不共享内存。

2. 进程之间的通信方式

答: (1) 匿名管道的方式:匿名管道的本质是在内存中的一个没有名字的文件,因此只适合父子进程之间的通信。 (2)有名管道:有名管道的本质是存储在磁盘上的一个有名字的文件,解决了匿名管道只能用在父子进程之间通信的问题,可以实现无联系的进程之间的通信。 (3)信号: 主要是用来通知某个事件已经完成。 (4)消息队列 :消息队列是在内核中的一个消息链表,遵循先进先出的顺序进行消息的传递,只有内核重启或者关闭数据才会丢失。 (5)信号量 :信号量是一个计数器,用于多进程之间对共享数据的访问,信号量的意图在于进程之间的同步。 (6)共享内存:让多个进程可以共享同一块内存空间,不同进程之间可以看到对方进程中对共享内存中数据的更新。 (7)socket:主要应用在网络中应用之间进行通信。

3. 介绍一下操作系统的内存结构

答:操作系统的内存结构主要包括 可移动的存储介质,外存(磁盘),磁盘缓存,内存,高速缓存,寄存器

4. 讲一下什么是DMA

答:DMA就是直接内存访问,就是不需要经过cpu 就可以直接与内存交互。

七、Linux相关

1. Linux查询CPU状态用什么命令

答:top 命令/lscpu命令/vmstat命令/

2. Linux查询日志用什么命令

答:vi /cat/less / tail -f 对某个文件进行动态的监控。

3. Linux服务器传文件命令

答: scp 本地文件地址 用户名@地址:/详细位置

4. 查看linux 进程的详细信息

答:ps -ef | grep 进程id

5. kill -9 和 kill -15 的区别

答: kill -9 是完全杀死进程,可能会带来数据丢失等副作用,就是windows下的进程管理器。kill -15 是发出信号 但是这个关闭进程的事情可能被阻塞或者挂起,就是windows 进程下的点红叉。

6. 端口的监听

答:netstat -ant | grep 3306

八、数据结构

1.了解哪些数据结构

2.有哪些树的结构?讲一下红黑树

3.冒泡和快速排序的原理

4.

九、其他

  1. 接口幂等性 幂等操作就是一个方法执行多次产生的影响都应该与第一次操作产生的影响是相同的。

  2. 事务回滚补偿

十、业务相关

1. 前端和后端数据是怎么对接的

2. 前端多个域名怎么处理的

3. 讲一下前后端分析

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务