腾讯笔经面经(微信事业群)

文章目录

    • 一、上手code
    • 二、技术面试

微信事业群
时间:20190831 时长:1小时30分
地点:牛客远程视频

一分钟自我介绍

一、上手code

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);
    }

二、技术面试

  1. “ == ”和equals的区别
== 是比较两个引用之间是否指向同一个对象,也就是比较两个引用存储的地址是否相等
equals在Object中比较的是两个对象的hashcode,日常我们实现基类时覆盖Object的equals方法,
例如User时,在equals中对属性name,age进行比较
  1. Hash算法你知道哪些?
我只知道一致性hash算法,然后拓展的说了下自己在项目中如何用到一致性哈希
算法的(Dubbo的一致性哈希算法实现负载均衡算法)
  1. 哈希碰撞的解决方案有哪些?说说开放定址法原理
- HashMap应用的链表法
- 开放定制法:感兴趣自行百度下,太多了,博主就不啰嗦了
  1. TreeMap和HashMap 的区别
看过源码,了解TreeMap是基于红黑树的,所以元素是有序的
HashMap是基于哈希算法的,元素是乱序存放
  1. 说说红黑树和Avl树
读者自行百度?
  1. 缓存淘汰算法
我的第一想法是Redis的LRU算法,之前看过Redis的源码,所以直接说了Redis几种常用的淘汰算法,
包括随机淘汰算法,FIFO淘汰算法,以及默认算法:删除不常用的key,使用双向链表维护所有被
使用的key,频繁使用的key存放在链表的表头附近,淘汰机制只需要淘汰表尾的元素
  1. TCP三次握手、四次挥手
  2. HTTP、HTTPS的区别
有必要和读者说说这儿:
- HTTPS相对于HTTP的文本传输变换为二进制传输,安全快捷
- HTTPS添加SSL协议,保障传输安全
- HTTPS默认支持长连接,采用多路复用机制
- HTTPS服务端支持反馈更多信息给应用端
  1. SSL过程
读者自行百度,博主建议挖透式学习
  1. 进程和线程的共同点和区别
共同点:拥有CPU的执行权、切换
区别:
- 进程可包含多个线程
- 进程管理资源,线程不能
- 进程之间的切换消耗比线程之间的切换大
- 线程之间共享进程的公共资源
  1. 进程之间的通信,线程之间的通信
进程之间可以通过RPC、消息中间件、Socket,全局变量等通信
线程之间可以通过共享变量、管道、wait/notify机制
  1. 你知道协程吧?
不知道?
  1. 你知道系统中的大小端吧?
不知道?
  1. 你用过BIO、NIO、AIO,说说他们之间的区别吧
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文件,有的话拷贝到用户态,否则,继续睡眠,等待被唤醒
  1. 内核态与用户态的交互过程
我按照自己理解说了下线程之间的上下文切换,进程之间的切换,主要是一些信息的拷贝,比较耗时,
如果切换次数过多的话,会对CPU的性能带来影响。
  1. 怎么看系统的CPU信息
我说到常用的TOP命令会看到系统的CPU使用率,内存等信息;还有vmstat查看上下文切换信息
  1. 给了我一段代码
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:方法是被线程调用的,所以方法存在于栈中,调用方法的过程进栈,返回方法的过程是出栈
  1. 给了一段代码,问我char和int各占几个字节,这几个变量一共占了多少字节,JVM内存对齐知道吗?
    代码
struct {
	char a;
	int b;
	char c;
}

回答:

- char和int分别各占2、4个字节
- 这几个变量共占了8个字节(这是我的回答,是错误的)
面试官问我知道JVM内存对齐知道吗?我第一反应想到的是JVM内存中的对象布局,
里面有一块内存叫对齐填充,意思是JVM对象头占用最少8个字节,
实例数据和对象头+内存填充的内存必须是8字节的整数倍

面试官纠正:三个变量共占用24个字节,因为这一块需要内存对齐,意思是按照内存分配最大的变量分配其
他变量的内存
  1. 用过什么数据库?在MySQL中使用什么引擎?
- 之前使用的MySQL,在阿里实习转正期间使用了Oracle
- 在MySQL中使用InnoDB引擎,还有一个叫MyISAM引擎
  1. 说说InnoDB和MyISAM的区别
- InnoDB支持事务,MyISAM不支持
- InnoDB支持行级锁,MyISAM不支持,只支持表级锁,当然InnoDB在where条件不是索引时也会使用表级锁
- InnoDB倾向于数据的更改,MyISAM倾向于查询,引用使用索引的不同
  1. 数据库事务有几个特性?分别是?
- 原子性
- 隔离型
- 一致性
- 持久性
  1. 说说隔离型中隔离级别有哪几种?分别解决什么问题
- 未提交读:会出现脏读、不可重复读、幻读
- 提交读:避免出现脏读,但是会出现不可重复读、幻读
- 可重复读:避免不可重复读,但是会出现幻读
- serializable:避免出现幻读
  1. MySQL如何解决在默认使用可重复读隔离级别时出现的幻读
数据库学习时间很久了,我记得当对某一行数据进行操作时,MySQL默认会对周围的行数据进行加锁,
避免出现幻读

面试官说相对地方了,它的专业名称叫间隙型锁
  1. 看你简历有分布式经历,使用Dubbo+Zookeeper,你说说分布式事务
我给大家推荐我自己总结的一篇文章吧,
几乎回答一样:https://blog.csdn.net/qq_40910541/article/details/97974388
  1. 我说到我在项目中排查过分布式事务空回滚的问题,和面试官一起交流了下事务空回滚的原因,解决方案
- 分布式事务空回滚概念:分布式事务一阶段提交之后丢失了二阶段的提交/回滚操作
- 分布式事务空回滚导致原因(项目):系统一阶段操作由于网络阻塞导致超时回滚,
一阶段恢复之后丢失二阶段提交/回滚操作,导致一阶段事务悬挂
- 排查问题过程:通过排查线上log日志发现二阶段回滚操作的时间比一阶段提交的时间要早1秒,确定是分布式事务空回滚导致
- 解决方案:1、我在系统中添加了事务悬挂预警,及时发现,及时解决。 2、TCC模块实现30秒拒绝空回滚

面试官交流也很愉快,说他们部门是60秒拒绝空回滚

你可能感兴趣的:(笔经面经,腾讯面试,微信事业群)