【牛客网面经整理】20200829多益面经整理

1.自我介绍
2.项目介绍一下,项目中遇到的一些问题,如何去解决的.

答:

3.聊一聊BIO和NIO.

答:网络模型的基本模型是CS模型,即两个线程之间的通信。服务器端提供IP和监听端口,客户端通过连接操作向服务器端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。
BIO:采用BIO通信模型的服务器,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完成后,通过输出流返回应答给客户端,线程销毁。即典型的请求应答通宵模型。主线程负责监听当有新的连接的时候创建一个新的子线程处理任务。
缺点:缺乏弹性伸缩能力,当客户量并发访问增加后,线程数量快速膨胀,系统的性能将急剧下降,随着访问量继续增大,系统最终死掉。

NIO:IO多路复用的好处就在于单个进程可以同时处理多个网络连接的IO。它的基本原理就是不再由应用程序自己监视连接,取而代之的是由内核替应用程序监视文件描述符。以select为例,当用户进程调用了select,那么整个进程会被阻塞,而同时,kernel会监视所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从内核拷贝到用户进程。
Reactor模式(反应堆设计模式),就是利用IO复用模型实现的,并且java当中的NIO模型就是这种模型;反应堆设计模式是一种处理并发服务请求,并将请求提交到一个或者多个服务处理程序的事件设计模式。当客户端请求抵达后,服务处理程序使用多路分配策略,由一个非阻塞的线程来接收所有的请求,然后派发这些请求至相关的工作线程进行处理。
NIO的组件:
1、Selector(选择器/多路复用器)。是NIO的核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。Selector提供选择已经就绪的任务的能力:Selector会不断检测注册在其上的Channel,如果某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后做出相应的操作。NIO监听的事件都定义在SelectionKey下:OP_CONNECT(只有SocketChannel会注册该操作,当客户端调用SocketChannel.connect()时,该操作就会就绪);
OP_READ(该操作对客户端和服务端的SocketChannel都有效,当OS的读写缓冲区中有数据可读时,该操作就会就绪);
OP_WRITE(该操作对客户端和服务端的SocketChannel都有效,当OS的写缓冲区中有空闲时间时(大部分时间都有),该操作就绪。一般情况下,不应该注册OP_WRITE事件,因为当注册后,写操作一直是就绪的,这样会导致Selector处理线程会占用整个CPU的资源。所以最佳实践是当确实有数据写入时再注册写事件,并且在写完后马上取消注册);
OP_ACCEPT(收到客户端的连接请求);
2、缓冲区:缓冲区是包在一个对象内的基本数据元素数组。Buffer类相比一个简单数组的优点,是将关于数据的数据内容和信息包含在一个单一的对象中。常用属性(capacity、position、limit、capcity、mark)
3、Channel:Channel可以理解为独立于CPU存在的;支持异步、可以双向传输数据、必须结合Buffer使用、性能高;

BIO和NIO的区别:BIO:面向流;阻塞IO;无选择器;
NIO:面向缓冲区;非阻塞IO;有选择器;

4.Mysql数据库的事务.

答:
概念:一个事务是由一条或多条对数据库操作的SQL语句,所组成的一个不可分割的单元;只有将事务中所有操作执行完了整个事务才会被提交给数据库;如果有部分事务处理失败,那么事务就要回退到最初的状态,因此事务要不全部执行成功,要么全部失败。
rollback:当SQL语句出错的时候可以通过rollback退回;
commit:只有当所有sql语句确认无误的时候,才提交给mysql,才会对数据造成持久性影响。
事务特性:A C I D
原子性:事务是一个不可分割的整体,事务必须具有原子特性,及当数据修改时,要么全执行,要么全不执行,即不允许事务部分完成;
一致性:一个事务执行之前和执行之后,数据库数据必须保持一致性状态。数据库的一致性状态必须由用户负责。
隔离性:当两个或者多个事务并发执行时,为了保证数据的安全性,将一个事务内部的操作与其他事务的操作隔离起来,不被其他正在执行的事务所看到。
持久性:事务完成后,DBMS保证它对数据库中的数据的修改是永久性的,即使数据库因为故障出错,也应该能够恢复数据。

设置事务:SET AUTOCOMMIT = 0

事务原理:
事务的实现原理=事务ACID特性的实现原理;
学习这些原理之前我们要先知道MySQL的Buffer Pool机制。
InnoDB作为MySQL的存储引擎,数据是存放在磁盘中的,但如果每次读写数据都需要磁盘IO,效率会很低。为此,InnoDB提供了缓存(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射,作为访问数据库的缓冲:当从数据库读取数据时,会首先从Buffer Pool中读取,如果Buffer Pool中没有,则从磁盘读取后放入Buffer Pool;当向数据库写入数据时,会首先写入Buffer Pool,Buffer Pool中修改的数据会定期刷新到磁盘中(这一过程称为刷脏)。Buffer Pool的使用大大提高了读写数据的效率,但是也带了新的问题:如果MySQL宕机,而此时Buffer Pool中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证,所以我们需要使用mysql中的日志来保证数据持久性的。
1、持久性实现原理:redo log日志
当数据修改时,除了修改缓存中的数据,还会在redo log记录这次操作;当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log 中的数据,对数据库进行恢复。redo log 采用的是WAL(预写式日志)所有修改先写入日志,再更新到缓存,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。
2、原子性实现原理:undo log日志
undolog 中会记录一条和你执行的sql语句意义相反的sql语句,当你rollback时就执行undo log中的sql语句。
实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚,靠的是undolog日志;当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚成之前的样子;
3、隔离性实现原理:锁机制+MVCC机制
记录锁:在索引记录上加锁;
间隙锁:在索引记录之间加锁
next-key locks:在索引记录上加锁,并且在索引记录之前的间隙加锁,相当于记录锁和间隙锁的一个结合;
共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同的数据集;
表锁:开销小,加锁快;不会出现死锁;锁定粒度大,发送锁冲突的概率最高,并发度也最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
MVCC机制:所谓MVCC机制就是尽量的不去使用这些锁,一旦这些锁加上之后事务与事务之间就变成了完全的串行执行,在隔离级别中串行化其实就是这样做的。mysql大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(mvcc)。MVcc的实现,是通过保存数据在某一个时间点的快照来实现的,每一个事务只操作自己版本下的数据。因此每一个事务无论执行多长时间看到的数据都是一样的。所以mvcc实现可重复读。

隔离性一共分了4中隔离级别(未提交读、已提交读、可重复读、序列化)
未提交读:会导致脏读、不可重复读、幻读,数据库一般不会使用;

可重复读:读取的数据都是不加锁的,但是数据的写入、修改和删除是需要加锁的(记录锁)。+(mvcc机制,只要没有commit那么修改的就是自己版本下的数据)

已提交读:读取的数据都是不加锁的,但是数据的写入、修改和删除是需要加锁的(记录锁)。解决了脏读问题?(mvcc机制,只要没有commit那么修改的就是自己版本下的数据)

序列化:所有锁都加了 没有mvcc机制,效率最低
读加共享锁,写加排他锁,读写互斥;
使用的悲观锁的理论,
(加的锁就是Next-Key Locks)实现简单,数据更加安全,但是并发能力非常差。如果你的业务并发的特别少或者没有并发,同时又要求数据及时可靠的话,可以使用这种模式。由于InnoDB引擎加的是行锁,并且是加在索引记录上,所以为了不产生幻读在还会加间隙锁。

4、一致性实现原理
持久性+隔离性+原子性共同实现了数据的一致性。

5.TCP三次握手

答:和TCP建立连接过程有关的首部结构;
SYN,seq,ACK,ack
状态变化:
客户端:关闭——同步已发送——已建立连接状态
服务器:关闭——收听——同步收到状态——已建立连接状态

1、一开始,服务器端B进程处于LISTEN状态,等待客户的连接请求。
2、客户端A打算建立连接,向B发出连接请求报文段(SYN=1,seq=x),这时首部中的同步位SYN-1,同时选择一个seq=x。此时服务器进程进入同步收听状态。
3、B收到连接请求报文段后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号ack=x+1,同时也为自己选择一个初始序号seq=y。(SYN=1,ACK=1,seq=y,ack=x+1)这时,客户进程进入同步已发送状态。
4、客户进程A收到B的确认后,还要向B给出确认。确认报文段ACK置1,确认号ack=y+1,而自己的序号seq=x+1.(ACK=1,ack=y+1,seq=x+1)此时TCP连接已经建立,A进入已建立连接状态
B收到A的确认后,也进入已建立连接状态。

为什么需要第三次呢?
防止已失效的连接请求报文段突然又传到了B因而产生错误。(比如A发送后经过时间延误到达B,这是一个已失效的报文段,但B认为连接已经开始就一直在等待A发来数据,就会造成资源浪费)

6.进程和线程

答:进程是计算机程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。简单来讲进程就是运行起来的程序。进程是线程的容器
线程:是操作系统能够进行运算调度的最小单位。是进程中的实际运作单位。

区别和联系:
联系:
1、一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
2、线程是操作系统可识别的最小执行单位和调度单位。资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一个进程中的多个线程共享代码段(代码和常量)、数据段(全局变量和静态变量)、扩展段(堆存储),但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。

区别:
1、地址空间和其他资源:进程间相互独立,同一进程的各个线程间共享。
2、通信:线程间可以直接通信,进程通信需要进程同步和互斥手段的辅助,以保证数据的一致性。
3、调度和切换:线程上下文切换比进程上下文切换快得多。
4、进程具有独立的空间地址,线程没有

串行:按照指令顺序,依次执行
并发:CPU快速切换给我们产生的同时执行的错觉
并行:真正的同时执行

7.多线程的应用场景

答:多线程:是指从软件或者硬件上实现多个线程并发执行的技术,具有多线程能力的计算机因有硬件支持能够在同一时间执行多于一个的线程,进而提升性能。
聊天;
浏览器;
后台任务;
桌面应用;

8.堆和栈的区别

答:在不同场景下,堆和栈代表不同的含义。
1、程序内存布局场景下,堆和栈表示的是两种内存管理方式;
2、数据结构场景下,堆和栈表示两种常用的数据结构;

栈:由操作系统自动分配释放,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。
堆:由程序员分配释放,程序结束后可以自动垃圾回收,分配方式类似于链表。

区别(六点):
1、管理方式不同。栈由操作系统自动分配释放,堆的申请和释放工作由程序员控制,容易产生内存泄漏;
2、空间大小不同。每个进程拥有的栈的大小远远小于堆的大小。
3、生长方向不同。堆的生长方向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低;
4、分配方式不同。堆都是动态分配的。栈有静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配。
5、分配效率不同。栈的效率比较高。
6、存放内容不同。栈(函数返回值、相关参数、局部变量、寄存器内容)。堆(由程序员来填充)

数据结构中的堆和栈;
堆:常用的树形结构,是一种特殊的完全二叉树。当且仅当满足所有节点的值总是不大于或不小于其父节点的值的完全二叉树被称之为堆。
栈:是一种运算受限的线性表,其限制是指只允许在表的一端进行插入和删除,先进后出。

9.session和cookie的区别,工作原理

答:
相同点:都是用来跟踪浏览器用户身份的会话方式。

不同点:1、cookie数据存放在客户的浏览器上;session数据存放在服务器上;
2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果主要考虑到安全应当使用session;
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能,如果考虑到减轻服务器性能方面应当使用cookie;
4、单个cookie在客户端的限制是3k。所以将登录信息等重要信息存放为session,其他信息如果需要保留可以存放在cookie中。

工作原理:
cookie:1、浏览器第一次发送请求到服务器端;
2、服务器端创建cookie,该cookie中包含用户的信息,然后将该cookie发送到浏览器端
3、浏览器再次访问服务器端时会携带服务器端创建的cookie
4、服务器端通过cookie中携带的数据区分不同的用户

session:1、浏览器端第一次发送请求到服务器端,服务器端创建一个session,同时会创建一个特殊的cookie(name为JSESSIONID的固定值,value为session对象的ID),然后将该cookie发送到浏览器;
2、浏览器端发送第n次请求到服务器端,浏览器端访问服务器端时就会携带刚才创建的cookie对象(name为JSESSIONID);
3、服务器端根据name为JSESSIONID的cookie的value,去查询session对象,从而区分不同用户;
若name为JSESSIONID的cookie不存在,返回1中重新去创建session与特殊的cookie;
若name为JSESSIONID的cookie存在,根据value中的sessionID去寻找session对象;(若value为SessionID不存在(session对象默认存活30分钟),根据value中的sessionID去寻找session对象;
若value为SessionID存在,返回session对象)

10.讲一讲消息队列

答:消息对列:是在消息的传输中保存消息的容器。
消息我们可以理解为在计算机中或整个计算机网络中传递的数据。
队列时基本的数据结构,具有先进先出的特点;
所以消息队列就是一个保存消息的容器,具有先进先出的特点;

为什么需要消息队列:
1、异步处理:在高并发的场景下缓解系统压力;
2、解耦

JMS规范:
JMS即java消息服务应用程序接口,是一个java平台中关于面向消息中间件(MOM)的API;
定义了两种消息通信模型:
1、点对点:消息生产者只需要将消息丢到消息队列中就可以了,一个消息只能有一个消费者,消费完之后消息就从队列中消失了。
2、发布订阅:允许一个消息可以有多个接受者。消息生产者产生一个消息后,把这个消息发送到Topic中,这个Topic可以同时有多个接收者在监听。

11.对于互联网公司加班的看法

答:我个人不排斥加班,喜欢有意义、有效率的加班

12.对于共享单车的看法

答:共享单车是一种交通工具租赁业务。是市场中的一种需求。共享单车利用新的技术,尤其是移动互联网技术,创新商业模式和产品与服务,更好的满足市场需求。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值