前端&后端基础部分面试题

题海战术 / 2022-10-14

关于面试题的一些思考

1.前端部分

1.1.关于Vue的父子组件值传参?

父传子:可以让父组件绑定子组件,然后子组件用props来接受父组件的参数
子传父:可用this.$emit来传递子组件的内容,父组件直接在methods中引用
父:用ref属性配合&refs.refname.方法名主动获取子组件内容
子:利用this.$parent来处理,等于获取到父组件的this

1.2.Vue的生命周期

  1.创建Vue实例
	2.beforeCreate:初始化生命周期和组件,用的少
	3.create:创建完成data和methods,通常用于获取列表数据发起axios请求
	4.beforeMount:create之后会开始解析<template>模板,这个钩子暂时还不无法获取到真实的DOM元素
	5.Mounted:Vue的元素UI已经渲染完,可以用mounted来操作真实元素
	6.beforeUpdate: 正要执行更新DOM元素更新操作
	7.Update:已经更新完成DOM元素
	8.beforeDestroy:准备销毁组件
	9.destroyed:生命周期结束,组件销毁

1.3.什么是Vuex?

  是关于Vue的状态管理,方便与兄弟组件进行通讯
	核心内容是state(具体状态)、getter(对外的获取状态)、mutation(更改状态的值)、action(提交mutation)、module(对更多的状态进行分组划分)

2.后端部分(Java)

2.1.基础部分

2.1.1.什么是原子操作

不会被打断的操作

2.1.2.关于volatile是什么?怎么用?

可以用在多线程环境中保证变量的可见性和有序性,但是不适用于复合性场景如i++等,比较适用于 布尔标记,触发器。

2.1.3.什么是不可变对象?他们对并发应用有什么帮助?

不可变对象类似于String、或者基本类型的包装类,他们的常量是在构造函数中创建的、他们是线程安全的

2.1.4.简述JVM模型、且用来存放什么数据?

  方法区:用来放常量和static对象
	堆:new出来的实例对象
	栈:方法执行、和地址引用
	本地方法栈:为Native方法服务(非Java提供的实现方法)
	程序计数器:记录当前线程的执行行号

2.1.5.几种常用的调试内存的工具?

栈:jstack  
内存:jmap   
dump堆信息:jhat

2.1.6.GC如何判断对象存活?

1.引用计数法:判断对象是否有被引用、如果引用计数器为0,则判断为死对象
2.可达性算法:通过GCRoots 向下索引引用链,如果没有引用链相连则不可用

2.1.7.关于垃圾回收机制的理解

垃圾回收机制是Java中一个在持续运行优先级比较低的线程、只有在线程空闲的时候才会进行扫描回收没有被任何引用的对象。

2.1.8.Java中垃圾回收的方法

标记清除法:通过标记进行统一回收和清除(问题是效率低、会产生不连续内存碎片)
复制算法:划分两个相等的内存,将第一个内存中存活的对象直接复制到第二个内存中,然后直接销毁第一个内存空间

2.1.9.关于类加载器

  启动类加载器:加载Java核心库无法直接引用
	扩展类加载器:用来加载Java的扩展库
	系统类加载器:可以根据Java应用路径来加载Java类
	用户自定义加载器: 通过继承类加载器来实现具体方法

2.1.10.BIO、NIO、AIO的区别简述

BIO是一个连接一个线程
NIO是一个请求一个线程,客户端发送的请求会注册到多路复用器上,多路复用器轮询到有I/O请求的时候才会创建线程
AIO是一个有效请求一个线程

2.1.11.NIO的组成

  buffer:与channel进行交互(缓冲区的数据读写)
	flip:反转缓冲区,用来切换读写模式
	clear:清除缓冲区
	rewind:重绕缓冲区将position重置为0
	DirectByteBuffer:减少一次系统空间到用户空间的拷贝
	Channel:IO源与目标源的通道,双向的只能与Buffer进行交互
	Selector:用一个单独的线程管理多个Channel,可监听读、写、连接、accept

2.1.12.NIO如何通过Buffer来缓冲数据?

  写入数据到Buffer,调用flip()方法,从Buffer中读取数据,调用clear()方法或者compact()方法。
	capacity: 缓冲区容量的大小,就是里面包含的数据大小。
	limit: 对buffer缓冲区使用的一个限制,从这个index开始就不能读取数据了。
	position: 代表着数组中可以开始读写的index, 不能大于limit。
	mark: 是类似路标的东西,在某个position的时候,设置一下mark,

2.1.13.什么是NIO?

NIO是一个非阻塞IO,基于Reactor模型实现。可以理解成由一个线程来处理大量的连接请求,通过一个线程轮询大量channel,每次获取到有事件的channel就启动一个线程来处理,核心就是非阻塞。selector线程不停的轮询channel,所有客户端请求都不会阻塞,无非就是需要排队等待。

2.1.14.为什么说NIO是同步非阻塞?

因为无论多少客户端都可以接入服务端,客户端接入并不会耗费一个线程,只会创建一个连接然后注册到selector上去罢了,你就可以去干其他你想干的其他事情了, 一个selector线程不断的轮询所有的socket连接,发现有事件了就通知你,然后你就启动一个线程处理一个请求即可,这个过程的话就是非阻塞的。但是这个处理的过程中,你还是要先读取数据,处理,再返回的,这是个同步的过程。

2.1.15.多路复用机制是如何支持海量连接的?

对Socket发起的连接不需要每个都创建一个线程,完全可以使用一个Selector来多路复用监听N多个Channel是否有请求,该请求是对应的连接请求,还是发送数据的请求,这里面是基于操作系统底层的Select通知机制的,一个Selector不断的轮询多个Channel,这样避免了创建多个线程,只有当莫个Channel有对应的请求的时候才会创建线程,可能说1000个请求, 只有100个请求是有数据交互的, 这个时候可能server端就提供10个线程就能够处理这些请求。这样的话就可以避免了创建大量的线程

2.1.16.NIO服务的建立过程?

1.先打开一个Selector:selector.open()
	2.创建服务端的channel
	3.绑定到某个端口上,并进行相关配置
	4.注册到selector上
	5.轮询拿到已经就绪的事件

2.1.17.关于线程池的执行原理?

	1.会先判断核心线程是否满,如果未满则安排线程执行task任务
	2.如果核心线程已满,则判断线程阻塞队列是否已满,未满则进入阻塞队列
	3.如果阻塞队列已满,则判断是否大于最大核心线程数,没大于则创建线程执行task任务
	4.如果已经是最大核心线程数,那么则会执行淘汰策略淘汰无法执行的task任务

2.1.18.Executors的四种线程池?

	1.newSingleThreadPool():单一线程池
	2.newFixedThreadPool():固定线程池
	3.newCacheThreadPool():缓存线程池- 有task任务进来创建线程缓存60s,60s后无调用则销毁
	4.newScheduledThreadPool():周期线程池-创建具有周期性和支持定时的线程

2.1.19.HashMap为什么采用红黑树,而不是AVL树?

	AVL树是高度平衡树,在新增删除后可能需要多次旋转来平衡
	红黑树则是弱平衡树,红黑树丛根到叶子最长路径不会超过最短路径2倍,旋转次数比较少在插入删除操作的时候

2.1.20.什么是CAS?应用场景?

	CAS:比较并交换 
	核心是存在三个值 V(内存地址) A(预期值) B(更新值)
	当V与A相等时,再更新B
	应用场景:ConcurrentHashMap、数据库CAS+乐观锁
	缺点:
		ABA问题:V与A相等但实际上V可能已经变化好几次了,CAS看不见
		解决方案:版本机制
		自旋周期过长

2.1.21.了解过Stream流吗?常用的几个方法?

	foreach 遍历、map 转换映射对象、 collection将处理结果变成集合对象
	max、min求集合中最大值最小值,要有比较器接口(类似Integer这些)
	count 返回元素个数
	distinct:去重
	filter:根据条件过滤
	sorted:排序
快乐与分享!