腾讯云智面试题

问题

1.手写单例模式,各种情况,怎么保证线程安全(这个没复习,跌跌撞撞蒙了三种)

懒汉式:
腾讯云智面试题_第1张图片

2.手写单例的过程中提到了synchronized和volatile,顺便问了这两个的实现原理


腾讯云智面试题_第2张图片

3. HashMap的底层实现,它为什么是线程不安全的(数组+链表+红黑树,为什么不安全不知道)

JDK1.7是数组+链表
JDK1.8是数组+链表+红黑树
在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况
在JDK1.7中,扩容数据时要进行把原数据迁移到新的位置,使用的方法transfer重新定位每个桶的下标,并采用头插法将元素迁移到新数组中。头插法会将链表的顺序翻转,这也是形成死循环的关键点。
在JDK1.8中,在并发执行put操作时会发生数据覆盖的情况

4. 知道哪些线程安全的集合类型?

ConcurrentHashMap、Hashtable

5.ConcurrentHashMap的实现原理

其实可以看出JDK1.8版本的ConcurrentHashMap的数据结构已经接近HashMap,相对而言, ConcurrentHashMap只是增加了同步的操作来控制并发,从JDK1.7版本的ReentrantLock+Segment+HashEntry,到JDK1.8版本中synchronized+CAS+HashEntry+红黑树。
1.数据结构:取消了Segment分段锁的数据结构,取而代之的是数组+链表+红黑树的结构。
2.保证线程安全机制:JDK1.7采用segment的分段锁机制实现线程安全,其中segment继承自 ReentrantLock。JDK1.8采用CAS+Synchronized保证线程安全
3.锁的粒度:原来是对需要进行数据操作的Segment加锁,现调整为对每个数组元素加锁 (Node)
4.链表转化为红黑树:定位结点的hash算法简化会带来弊端,Hash冲突加剧,因此在链表节点数量大于8时,会将链表转化为红黑树进行存储。
5.查询时间复杂度:从原来的遍历链表O(n),变成遍历红黑树O(logN)。

6.HashTable的底层原理

HashTable的主要方法的源码实现逻辑,与HashMap中非常相似,有一点重大区别就是所有的操作都是通过synchronized锁保护的。只有获得了对应的锁,才能进行后续的读写等操作。

7. MySQL索引结构,为什么用B+树

b+树,是b树的一种变体,查询性能更好。 b+树相比于b树的查询优势:
1.b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更 “矮胖”。B树不管叶子节点还是非叶子节 点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致 IO 操作变多,查询性能变低;
2.b+树查询必须查找到叶子节点,b树只要匹配到即可直接返回。因此 b+树查找更稳定(并不慢),必须查找到叶子节点;而B树,如果数据在根节点,最快,在叶子节点最慢,查询效率不稳定。
3.对于范围查找来说,b+树只需遍历叶子节点链表即可,并且不需要排序操作,因为叶子节点已经对索引进行了排序操作。b树却需要重复地中序遍历,找到所有的范围内的节点。

8.场景题:sql查询很慢怎么排查(先检查sql语句,看看是否命中索引,是否符合最左前缀原则,用explain查看sql的执行情况)

9.说说最左前缀原则

从最左边为起点开始连续匹配,遇到范围查询(<、>、between、like(某些like))会停止匹配。

10.MySQL的主从复制过程

原理

  • master 服务器将数据的改变记录二进制 binlog 日志,当 master 上的数据发生改变时,则将其改变写入二进制日志中;
  • slave 服务器会在一定时间间隔内对 master 二进制日志进行探测其是否发生改变,如果发生改变,则开始一个 I/OThread 请求 master 二进制事件;
  • 同时主节点为每个 I/O 线程启动一个 dump 线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动 SQL 线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后 I/OThread 和 SQLThread 将进入睡眠状态,等待下一次被唤醒。

也就是

  • 从库会生成两个线程,一个 I/O 线程,一个 SQL 线程;
  • I/O 线程会去请求主库的 binlog,并将得到的 binlog 写到本地的 relay-log(中继日志)文件中;主库会生成一个 log dump 线程,用来给从库 I/O 线程传 binlog;
  • SQL 线程,会读取 relay log 文件中的日志,并解析成sql语句逐一执行。

如果一主多从的话,这时主库既要负责写又要负责为几个从库提供二进制日志。此时可以稍做调整,将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从。或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些

11.解决Mysql主从同步数据一致性的问题

原理

  • master 服务器将数据的改变记录二进制 binlog 日志,当 master 上的数据发生改变时,则将其改变写入二进制日志中;
  • slave 服务器会在一定时间间隔内对 master 二进制日志进行探测其是否发生改变,如果发生改变,则开始一个 I/OThread 请求 master 二进制事件;
  • 同时主节点为每个 I/O 线程启动一个 dump 线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动 SQL 线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后 I/OThread 和 SQLThread 将进入睡眠状态,等待下一次被唤醒。

也就是

  • 从库会生成两个线程,一个 I/O 线程,一个 SQL 线程;
  • I/O 线程会去请求主库的 binlog,并将得到的 binlog 写到本地的 relay-log(中继日志)文件中;主库会生成一个 log dump 线程,用来给从库 I/O 线程传 binlog;
  • SQL 线程,会读取 relay log 文件中的日志,并解析成sql语句逐一执行。

异步复制、半同步复制、增强半同步复制,解决主从同步时的数据不一致问题。
异步复制
mysql的默认复制机制是异步的,主库执行完客户端提交的事务后会立刻把结果返回给客户端,并不关心从库是否接收并处理,会导致如果主DB宕机了,就可能导致主机上提交的事务可能并没有同步到从db中,主从之间无法保证严格一致的模式。
半同步复制
MySQL在5.5中引入了半同步复制,主库执行完客户端提交的事务后并不会立刻返回给客户端,而是强制立即将数据同步给从库,从库将日志写入到自己的reply log中后,接着会返回一个ack给主库,主库等待至少一个从库接收到ack才返回给客户端;相对于异步复制,提高了数据的安全性,但也提高了延迟,最少是一个TCP/IP往返的时间,所以最好在低延迟的网络中使用。
增强半同步复制
事务线程要等待所有从库的复制成功响应。

12.算法题

  1. 算法题:求矩阵的最小路径,每次只能往右或下移动,写出来后问了下思路,以及对应的模型(动态规划)
  2. sql题:一个学生成绩表,字段有学生姓名、班级、成绩,求各班前十名(太久没写sql忘得差不多了。。)

你可能感兴趣的:(java,面试)