前端部分:
1.setTimeOut函数里,时间设置为0代表什么意思,会不会立刻执行
会在队列最后添加一个事件,要等待其他任务事件处理完成才会处理。
2.== 和 === 的区别
3.相对定位和决定定位的区别:
绝对定位:绝对定位是相对于元素最近的已定位的祖先元素(即是设置了绝对定位或者相对定位的祖先元素)。如果元素没有已定位的祖先元素,那么它的位置则是相对于最初的包含块(body)
相对定位:相对定位是相对于元素在文档中的初始位置,在使用相对定位时,无论是否进行移动,元素仍然占据原来的空间
4.鼠标悬停在一个div上时,修改div的背景颜色怎么实现
5.有两个div, 是父子关系, 怎么实现子div在父div里水平,垂直居中
最优做法是flex布局:display: flex;align-items: center;justify-content: center;
6.JavaScript中find()和filter()的区别
find()主要应用于查找第一个符合条件的数组元素
filter()返回的是数组,数组内是所有满足条件的元素
7.let 与 var 的区别:
var是函数作用域,而let是块作用域
var可以允许重复声明相同的变量,后者会覆盖前者,let则不能重复声明相同的变量
var声明的变量有变量提升特性,let声明则没有这个特性
8.const是什么
声明常量时,一旦声明,常量的值就不能改变
声明对象时,指向对象的内存地址不变,对象的内容可以改变
9.Promise的用法:
Promise对象是一个构造函数,用来生成Promise实例
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
10.箭头函数里的this和普通函数的this的区别
对于普通函数来说,内部的this指向函数运行时所在的对象,是动态的
箭头函数它没有自己的this对象,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的
数据库部分:
Mysql中的存储引擎有哪些
InnoDB
MyISAM
Memory
InnoDB引擎与MyISAM引擎的区别 ?
InnoDB引擎, 支持事务, 而MyISAM不支持。
InnoDB引擎, 支持行锁和表锁, 而MyISAM仅支持表锁, 不支持行锁。
InnoDB引擎, 支持外键, 而MyISAM是不支持的。
索引方面:MyISam中索引和数据是分开存,InnoDB是都在一个文件
Mysql中索引的数据结构,这种结构有什么特点
哪些情况下会出现索引失效
什么是覆盖索引
什么是聚簇索引,什么是非聚簇索引
Mysql的事务隔离级别有哪些,默认级别是什么
Mysql事务原理
redo.log + undo.log 实现了事务的一致性,原子性,持久性
锁 + MVCC 实现了事务的隔离性
Mysql锁的分类
表级锁
表锁
加锁:lock tables 表名... read/write
释放锁:unlock tables / 客户端断开连接
元数据锁
加锁过程是系统自动控制
意向锁
行级锁
行锁 :锁定单个行记录的锁
间隙锁 :锁定索引记录间隙(不含该记录)
临键锁 :同时锁住数据,并锁住数据前面的间隙Gap
微服务部分:
springboot中读取配置文件的顺序是什么 ps:下面的优先级顺序依次升高
1.classpath/xxx.yml
2.classpath/config/xxx.yml
3.项目目录下/xxx.yml
4.项目目录下/config/xxx.yml
springboot的自动装配原理是什么
Springboot构造函数逻辑:
1.初始化一些变量
2.把主类保存为primarySource
3.推断应用类型
4.实例化SpringFactoryInstance,并放入缓存
5.获取初始化器和监听器
6.推断主类
Springboot中run方法的逻辑:
1.开始计时
2.创建启动上下文
3.设置无显示器也能启动
4.获取监听器并启动
5.保存启动参数【启动时传入】
6.准备环境【Maven变量,类路径,配置文件等】
7.忽略Bean信息
8.打印Banner
9.创建应用上下文
创建BeanFactory
10.准备上下文
11.刷新上下文
自动装配
12.刷新上下文后置处理
空方法
13.结束计时
14.调用runner
BeanFactory与FactoryBean的区别是什么
SpringBoot中Bean是如何创建的
通过反射调用构造方法创建的
Springboot中Bean的生命周期是什么
加载解析Bean定义--》实例化--》属性填充--》初始化--》销毁
SpringBoot如何解决循环依赖,为什么需要第三级缓存
Java基础部分:
1.创建对象有哪几种方式
new
反射
clone
clone方法执行的是浅拷贝
在内存中开辟一块新的内存,基础变量是直接拷贝过去,引用对象是拷贝引用
2.八大数据类型
int, short, char, long, byte, float, double, boolean,
3.== 和 equals 的区别是什么?
equals():用来检测两个对象是否相等,即两个对象的内容是否相等。
==:用于比较引用和比较基本数据类型时具有不同的功能
基础数据类型:比较的是他们的值是否相等
引用数据类型:比较的是引用的地址是否相同
Integer a = 127; Integer b = 127; a == b ? 128呢?
4.创建线程有哪几种方式
继承Thread类
实现Runnable
实现Callable
Runnable和Callable有什么区别
Callable可以获取线程的返回值,能抛异常
Runnable没有返回值,也不会抛异常
5.voliate关键字的作用
内存可见性
防止指令重排
不保证原子性
6.Lock与Synchronized的区别,开发中该如何选择呢?
synchronized是java中的关键字,底层采用的是objectMonitor
synchronized可以写在需要同步的对象、方法或者是特定代的码块中
synchronized只提供了非公平锁的实现
synchronized自动释放锁
lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断
Lock可以通过trylock来知道有没有获取锁,而synchronized不能
Lock需要手动释放锁,加锁,解锁都需要显示指定
synchronized使用了object类的wait和notify进行等待和唤醒, lock使用了condition接口进行等待和唤醒(await和signal);
7.创建线程池的各个参数的含义
第一个:线程池里核心线程数
第二个:线程池里的最大线程数
第三个:线程池里空闲线程的最长存活时间
第四个:存活时间的单位
第五个: 线程工作队列
第六个:创建线程的工厂
第七个:拒绝策略
8.线程池工作原理,有哪些拒绝策略
任务提交时,先看线程池里的数量有没有达到核心线程数,如果没达到,就创建新的线程
如果达到了,就把新提交的任务放到任务队列中
如果任务队列也满了,这时提交任务时,就判断线程池的线程数有没有达到线程池能容纳的最大线程数,如果没达到,就创建新的线程
如果达到的最大的线程数,就执行拒绝策略
如果最大线程数大于核心线程数,超过闲置时间后,线程会被回收,最终保持线程数等于核心线程数
4种拒绝策略
拒绝接受新任务,然后抛异常 ps: 默认的拒绝策略
丢弃任务,不抛异常
丢弃队列中最前面的任务,然后接受新提交的任务
由提交任务的线程执行此任务
9.JVM的内存区域划分
程序计数器
虚拟机栈
栈中的数据都是以栈帧(Stack Frame)的格式存在
每个栈帧中存储着:
局部变量表
动态链接
操作数栈
方法的返回地址
方法区
元空间是方法区的实现,是jdk1.8中的
永久代也是方法区的实现,是jdk1.7中的
堆
1/3 年轻代
Eden空间和另外两个survivor空间缺省所占的比例是8:1:1
2/3 老年代
本地方法栈
10.什么是Minor GC ?什么是Major GC ?, 两者之间有什么关系
Minor GC是新生代区的垃圾回收,当Eden区的空间不够的时候需要进行MinorGC策略回收
Major GC是老年代的垃圾回收,老年代空间不足时,会先尝试触发Minor GC。Minor GC之后空间还不足,则会触发Major GC。
基本上进行一次Major GC 就会伴随进行一次 Minor GC
11.一个Java对象包含哪些内容:
对象头
实例数据
对齐填充
12.对象头包含哪些内容:
对象的hashcode
分代年龄
偏向线程ID
锁状态标志
13.HashMap put数据的过程
1.先判断Table是否为空或者长度是否为0,如果成立,进行一次resize()
2.根据数组长度 - 1,与key的Hash值去模,得出要插入的数组下标,判断该下标是否有元素,如果没有,就直接插入到该位置
3.如果该下标下有元素:
3.1:判断该元素的key是否和要插入的key一模一样,先用 == 再用 equals 判断,如果一样,用新值替换就值
3.2:如果key不一样,就判断该位置的元素是不是TreeNode,如果是,就插入
3.3:如果该位置的元素是链表结构,就插入到链表的尾部,插入后,如果链表的长度大于等于8,就进行树化
4.记录modCount
5.判断是否需要扩容
key的Hash计算方法:(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)
put方法里,计算hash, 然后调用 putVal()方法,进行添加数据
HashMap扩容的长度为什么是原来的2倍
计算插入数组下标公式:(n-1) & hash,2n - 1 的二进制数都是1,
保证了每次扩容之后新数组的最大索引值对应的二进制数为全1,每位都能参与位运算,能够最大化的分散到HashMap所有的 bucket 中,减少Hash冲突
当 new HashMap(10) 时,hashMap 初始化的数组长度是10么?
ConcurrentHashMap线程安全的原理
1.7:采用分段锁
1.8:synchronized + CAS
synchronized体现在要添加的索引位置上已经有元素了,再往上面添加时
CAS体现在要添加的位置没有元素时
14.Lock获取锁的过程:
非公平:
1.直接调用tryAcquire()尝试获取锁,如果加锁失败,就把当前线程实例化成一个Node,加入队列的尾部
tryAcquire()逻辑:
1.先获取到当前线程
2.获取state字段的值,判断值是否为0
3.如果为0,判断队列里是否还有其它节点,如果没有,就尝试加锁,加锁成功后,就把exclusiveOwnerThread设置为自己
4.如果不为0,就判断当前线程是否和拿到锁的线程一样,如果成立,表示可重入,计数加1,如果不一样,就加锁失败
2.判断刚实例化的Node的前驱节点是否为头节点,如果是头节点,就再次尝试获取锁,
2.1:如果取到了,就把自己设置为头节点:
2.2:如果没有取到,就判断自己是否需要挂起
判断是否需要挂起条件:当前节点的前驱节点状态为SIGNAL时,当前节点需要挂起
前驱节点状态大于0时,表示取消等待,就获取前驱的前驱,直到状态不大于0,然后设置前驱节点为SIGNAL
ps: 如果只有两个线程AB,A拿到了锁,B尝试拿锁的时候,是拿不到的,那么B就加入到队列中,又因为B的前驱节点是头节点,因此B还会再次尝试一下获取锁,如果还是获取不到,就判断一下B是否需要挂起,判断后B不需要挂起,那么B就会再次执行获取锁的步骤,一直重复到拿到锁为止,因为不知道要循环多少次,因此for循环里没有限制循环次数
中间键部分:
如何避免消息队列中消息的重复消费
建一个本地事务表【Redis或者Mysql都可以】,消费者在消费的时候,先判断库里有没有这个记录,如果没有,就先把消息保存在数据库,状态标记为未消费,然后再正常消费,消费万修改状态为已消费
什么是幂等性,如何实现
同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用
利用 redis 执行 setnx 命令,天然具有幂等性。从而实现不重复消费
RabbitMQ如何保证消息不丢失?
生产端:1.开启发布确认,publisher-confirm-type: correlated,消息到达交换机后,就会调用回调函数
2.开启回退消息通知,那些没法被成功路由的消息就会触发回调函数,returnCallback
消费端:开启手动ack
网友评论