微信事业群
时间:20190831 时长:1小时30分
地点:牛客远程视频
一分钟自我介绍
1、手写字符串的反转
我的code:
public String stringReserve(String inputString) {
int length = inputString.length();
if(inputString == null || length == 0) {
return null;
}
return reverse(inputString.toCharArray(), 0, length-1);
}
private String reverse(char[] str, int start, int end) {
while (start < end) {
char temp = str[start];
str[start++] = str[end];
str[end--] = temp;
}
return str.toString();
}
2、 手写双向链表
我的code:
public class LinkedList{
private Node root;
public class Node{
private Object data;
private Node preNode;
private Node next;
}
public Node getRoot(){
return this.root;
}
public void setRoot(Node root) {
this.root = root;
}
}
3、按照顺序合并两个链表,手写代码
我的code:
public Node merge(LinkedList first, LinkedList second) {
if(first == null && second == null) return null;
if (first != null && second == null) {
return first.getRoot();
}
if (first == null && second != null) {
return second.getRoot();
}
Node newNode;
Node temp;
Node temp1 = new Node();
Node temp2 = new Node();
if (first.getRoot().data < second.getRoot().data) {
newNode = first.root;
temp = newNode.next;
temp1 = temp;
}
else {
newNode = second.root;
temp = newNode.next;
temp2 = temp;
}
while (temp1 != null && temp2 != null) {
if(temp1.data < temp2.data) {
temp.next = temp1;
temp1 = temp1.next;
}
else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
}
if (temp2 != null) {
temp.next = temp2;
}
return newNode;
}
4、手写快排算法,问了快排的时间复杂度,什么情况是最差的
我的回答:快排时间最好情况是O(nlogn),最差O(n*n);最差情况是目标排序数组是有序的,基数每次移动都是移动一步,类似于冒泡排序
我的code:
public void quickSort (int[] array, int start, int end) {
if (array == null || array.length == 0) {
return;
}
int i = start, j = end;
int temp = array[start];
while (i < j) {
while(array[j] > temp && i < j) {
--j;
}
while(array[i] <= temp && i < j) {
++i;
}
int x = array[i];
array[i] = array[j];
array[j] = x;
}
array[start] = array[i];
array[start] = temp;
quickSort(array, start, i-1);
quickSort(array, i+1, end);
}
== 是比较两个引用之间是否指向同一个对象,也就是比较两个引用存储的地址是否相等
equals在Object中比较的是两个对象的hashcode,日常我们实现基类时覆盖Object的equals方法,
例如User时,在equals中对属性name,age进行比较
我只知道一致性hash算法,然后拓展的说了下自己在项目中如何用到一致性哈希
算法的(Dubbo的一致性哈希算法实现负载均衡算法)
- HashMap应用的链表法
- 开放定制法:感兴趣自行百度下,太多了,博主就不啰嗦了
看过源码,了解TreeMap是基于红黑树的,所以元素是有序的
HashMap是基于哈希算法的,元素是乱序存放
读者自行百度?
我的第一想法是Redis的LRU算法,之前看过Redis的源码,所以直接说了Redis几种常用的淘汰算法,
包括随机淘汰算法,FIFO淘汰算法,以及默认算法:删除不常用的key,使用双向链表维护所有被
使用的key,频繁使用的key存放在链表的表头附近,淘汰机制只需要淘汰表尾的元素
有必要和读者说说这儿:
- HTTPS相对于HTTP的文本传输变换为二进制传输,安全快捷
- HTTPS添加SSL协议,保障传输安全
- HTTPS默认支持长连接,采用多路复用机制
- HTTPS服务端支持反馈更多信息给应用端
读者自行百度,博主建议挖透式学习
共同点:拥有CPU的执行权、切换
区别:
- 进程可包含多个线程
- 进程管理资源,线程不能
- 进程之间的切换消耗比线程之间的切换大
- 线程之间共享进程的公共资源
进程之间可以通过RPC、消息中间件、Socket,全局变量等通信
线程之间可以通过共享变量、管道、wait/notify机制
不知道?
不知道?
BIO:同步阻塞式,一个socket请求对应一个线程处理,耗时耗资源
NIO:同步非阻塞,socket请求由线程池来处理(boss、worker线程池原理)
AIO:异步化
我另外解释了下系统底层的实现select、poll、epoll的区别:
- select每次执行select方法,都会从用户态拷贝所有的fd文件到内核态中,存储在内核态的数组中,数组大小默认1024个,存放的fd文件数量受限制
- select采用轮训的方式寻找有事件的fd文件
- 对有事件的fd文件再次拷贝到用户态做相应的处理
- epoll有三个函数:epoll_create、epoll_ctl、epoll_wait,epoll_create在内核态启动时创建红黑树和就绪队列,红黑树相对于select的数组所容纳的fd文件数量更多,效率更高
- epoll_ctl负责将用户态的fd文件符拷贝到内核的红黑树中,并且制定相应的回调接口,当fd文件符有事件时,回调接口,将fd文件移动到就绪队列中
- epoll_wait负责监听就绪队列是否有就绪的fd文件,有的话拷贝到用户态,否则,继续睡眠,等待被唤醒
我按照自己理解说了下线程之间的上下文切换,进程之间的切换,主要是一些信息的拷贝,比较耗时,
如果切换次数过多的话,会对CPU的性能带来影响。
我说到常用的TOP命令会看到系统的CPU使用率,内存等信息;还有vmstat查看上下文切换信息
String a = "aaaaaa";
int b;
int test (int i) {
b = i;
}
int main () {
int temp = 0;
int c = test(temp);
return c;
}
问在进程中这些信息的布局
我的回答:
变量a:首先字符串在JVM中是常量,所以a变量肯定存放在常量池中,而常量池存放在JVM中的永久代中。
变量i、b、temp、c:基本变量类型和临时变量都是存放在JVM栈的栈桢中,每个栈桢包含临时变量,变量值等信息
方法test:方法是被线程调用的,所以方法存在于栈中,调用方法的过程进栈,返回方法的过程是出栈
struct {
char a;
int b;
char c;
}
回答:
- char和int分别各占2、4个字节
- 这几个变量共占了8个字节(这是我的回答,是错误的)
面试官问我知道JVM内存对齐知道吗?我第一反应想到的是JVM内存中的对象布局,
里面有一块内存叫对齐填充,意思是JVM对象头占用最少8个字节,
实例数据和对象头+内存填充的内存必须是8字节的整数倍
面试官纠正:三个变量共占用24个字节,因为这一块需要内存对齐,意思是按照内存分配最大的变量分配其
他变量的内存
- 之前使用的MySQL,在阿里实习转正期间使用了Oracle
- 在MySQL中使用InnoDB引擎,还有一个叫MyISAM引擎
- InnoDB支持事务,MyISAM不支持
- InnoDB支持行级锁,MyISAM不支持,只支持表级锁,当然InnoDB在where条件不是索引时也会使用表级锁
- InnoDB倾向于数据的更改,MyISAM倾向于查询,引用使用索引的不同
- 原子性
- 隔离型
- 一致性
- 持久性
- 未提交读:会出现脏读、不可重复读、幻读
- 提交读:避免出现脏读,但是会出现不可重复读、幻读
- 可重复读:避免不可重复读,但是会出现幻读
- serializable:避免出现幻读
数据库学习时间很久了,我记得当对某一行数据进行操作时,MySQL默认会对周围的行数据进行加锁,
避免出现幻读
面试官说相对地方了,它的专业名称叫间隙型锁
我给大家推荐我自己总结的一篇文章吧,
几乎回答一样:https://blog.csdn.net/qq_40910541/article/details/97974388
- 分布式事务空回滚概念:分布式事务一阶段提交之后丢失了二阶段的提交/回滚操作
- 分布式事务空回滚导致原因(项目):系统一阶段操作由于网络阻塞导致超时回滚,
一阶段恢复之后丢失二阶段提交/回滚操作,导致一阶段事务悬挂
- 排查问题过程:通过排查线上log日志发现二阶段回滚操作的时间比一阶段提交的时间要早1秒,确定是分布式事务空回滚导致
- 解决方案:1、我在系统中添加了事务悬挂预警,及时发现,及时解决。 2、TCC模块实现30秒拒绝空回滚
面试官交流也很愉快,说他们部门是60秒拒绝空回滚