天融信一面记录--2022.03.09
0.自我介绍
1.数组和链表的区别
2.ArrayList扩容机制
3.HashMap底层原理
4.我想要一个key可重复的Map
5.我想要一个排序的Map
6.我想要一个线程安全的Map
7.实现线程几种方式
8.Runnable和Callable的区别
9.Callable的返回值如何获取
10.多线程如何访问共享变量
11.sleep 和wait方法的区别
12.如何使线程阻塞
13.线程的几种状态
14.synchronized关键字和valotile关键字区别
15.Java内存模型
16.堆结构的细分
17.程序计数器是干什么的
18.双亲委派机制,为什么使用这种机制
19.索引失效的情况
20.如何查看SQL是否走索引
21.数据库事务的四大特性
22.数据的事务隔离级别,MySQL默认是哪种
23.MVCC机制
24.mybatis缓存怎么实现的
25.springcloud组件
26.openfign你是如何使用的
27.服务如何注册到注册中心
28.ES你知道的概念
29.Kafka你知道的概念
30.docker 和虚拟机的区别
0.自我介绍
1.数组和链表的区别
1.空间是否连续: 数组在内存中是连续的,链表在内存中元素空间可以在任意地方,不需要连续
2.插入删除效率: 数组头插和头删的时间复杂度为O(N),链表在任意位置插入时间复杂度为O(1)
3.查询效率: 数组随机查询时间复杂度为O(1),链表随机查询时间复杂度为O(N)
2.ArrayList扩容机制
ArrayList的初始化容量为10,在新增元素的时候,会判断当前容量是否充足,充足则不进行扩容,
不充足则计算扩容的容量,为当前旧容量+旧容量右移一位,即当前旧容量的1.5倍,然后将元素拷贝至新数组
3.HashMap底层原理
Jdk1.7 数组 + 链表
Jdk1.8 数组 + 链表 + 红黑树
4.我想要一个key可重复的Map
IdentityHashMap
5.我想要一个排序的Map
TreeMap
6.我想要一个线程安全的Map
ConcurrentHashMap
Collections.synchronizedMap
HashTable
7.实现线程几种方式
1.继承Thread类
2.实现Runnable
3.实现Callable
4.使用线程池ThreadPoolExecutor
5.使用Future
6.使用CompletableFuture
8.Runnable和Callable的区别
1.Runnable没有返回值,Callable有返回值
2.Runnable不能抛出异常,Callable可以获取到异常
9.Callable的返回值如何获取
将任务放在FutureTask中,启动线程后get出来,代码如下
public class CallableTest {
public static class CallerTask implements Callable<String> {
@Override
public String call() throws Exception {
return "caller task";
}
}
public static class CallerExceptionTask implements Callable<String> {
@Override
public String call() throws Exception {
throw new RuntimeException("caller task throw exception");
}
}
public static void main(String[] args) {
//创建异步任务
FutureTask<String> futureTask = new FutureTask<>(new CallerExceptionTask());
//启动线程
new Thread(futureTask).start();
String s = null;
try {
s = futureTask.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
System.out.println("异步任务返回值:" + s);
}
}
10.多线程如何访问共享变量
1.使用 valotile 关键字实现共享变量的可见性
2.使用 synchronized 关键字实现共享变量的可见性以及操作的原子性
3.使用 java.util.concurrent类来实现共享变量的可见性
11.sleep 和wait方法的区别
1.sleep方法不会释放锁,wait方法会释放锁
2.sleep方法是Thread类中的,wait方法是Object类中
3.sleep方法到了时间会自动唤醒,wait方法需要notify或者notifyAll唤醒
4.sleep方法需要try catch ,而wait方法不需要
5.sleep方法可以在方法内任意位置,wait方法必须同步代码块里
12.如何使线程阻塞
调用线程的join方法
13.线程的几种状态
初始化(NEW)、可运行(RUNNABLE)、等待(WAITING)、超时等待状态(TIMED_WAITING)、阻塞(BLOCKED)、终止(TERMINATED)
14.synchronized关键字和valotile关键字区别
- volatile关键字解决的是变量在多个线程之间的可见性;而sychronized关键字解决的是多个线程之间访问共享资源的同步性。
- volatile只能用于修饰变量,而synchronized可以修饰方法,以及代码块。(volatile是线程同步的轻量级实现,所以volatile性能比synchronized要好,并且随着JDK新版本的发布,sychronized关键字在执行上得到很大的提升,在开发中使用synchronized关键字的比率还是比较大)
- 多线程访问volatile不会发生阻塞,而sychronized会出现阻塞。
- volatile能保证变量在多个线程之间的可见性,但不能保证原子性;而sychronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公有内存中的数据做同步。
15.Java内存模型
Java堆、方法区(元空间)、Java虚拟机栈、本地方法栈、程序计数器
16.Java堆空间细分
Java堆细分可以分为新生代和老年代,新生代分为Eden区和S0区和S1区
17.程序计数器是干什么的
Java字节码执行的行号指示器,涉及到线程切换时记录当前线程执行到哪了
18.类加载器,双亲委派机制,为什么使用这种机制
类加载器:启动类加载器、扩展类加载器、应用类加载器
双亲委派机制:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父类加载反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
好处:1.避免重复加载、防止核心类被篡改
启动类加载器负责加载<JAVA_HOME>/lib目录
扩展类加载器负责加载<JAVA_HOME>/lib/ext目录
应用类加载器负责加载类路径目录(ClassPath)
19.索引失效的情况
1.字段数据区分度不高
2.索引坏掉
3.like查询使用左模糊
4.建立了复合索引,但查询条件没有以复合索引的第一个字段开始
5.查询列使用了函数
6.查询列使用了运算
20.如何查看SQL是否走索引
使用Explain关键字查看SQL语句
21.数据库事务的四大特性
原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency)
事务前后数据的完整性必须保持一致。
隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
22.数据的事务隔离级别,MySQL默认是哪种
读未提交、读已提交、可重复读、串行化
MySQL默认的事务隔离级别是:可重复读
23.MySQL的MVCC机制
https://zhuanlan.zhihu.com/p/324440184
https://cloud.tencent.com/developer/article/1876227
24.mybatis缓存怎么实现的
https://tech.meituan.com/2018/01/19/mybatis-cache.html
25.springcloud组件
项目中常用的是:Eureka、OpenFeign、Hystrix、Zuul
26.服务如何注册到注册中心
引入Eureka客户端依赖、在配置文件中增加注册中心地址、在启动类上增加@EnableDiscoveryClient注解
27.openfeign你是如何使用的
引入openfeign依赖、写一个接口类,使用@FeignClient注解标明他,写上方法并注解调用地址及参数
28.ES你知道的概念
https://blog.csdn.net/laoyang360/article/details/52244917
29.Kafka你知道的概念
https://www.jianshu.com/p/97011dab6c56
30.docker 和虚拟机的区别
1、启动速度
启动虚拟机需要先启动虚拟机的操作系统,再启动应用,这个过程非常慢;
而启动 Docker 相当于启动宿主操作系统上的一个进程。
2、占用资源
虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 CPU 资源,一台机器只能开启几十个的虚拟机。而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。
3、隔离性
与虚拟机相比,docker隔离性更弱,docker属于进程之间的隔离,虚拟机可实现系统级别隔离。
4、安全性
docker的安全性也更弱。Docker的租户root和宿主机root等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户root权限和宿主机的root虚拟机权限是分离的,并且虚拟机利用如Intel的VT-d和VT-x的ring-1硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击