面试题随记二

从7月2号开始,到7月21号结束,14个工作日,参加了15场面试。其中:

滴滴:面4场

美团:面3场

自如:面2场

小米:面3场

去哪儿:面1场

Boss直聘:面2场

工作3年,终于拿到了心仪的offer,在这里做一个记录。

因平时上班事情比较多,再加上面试比较密集,所以没能及时的对每一次面试做一个复盘,导致面试遇到的好多东西都已经忘了,所以这里就只能捡我在微信文件助手里面的几个有意思的记录来写了。

好记性不如烂笔头,写出来一是给自己做一个笔记,二是也希望分享出来能对其他朋友有所帮助。


美团二面

1、如果因为一些原因,线上Redis挂了,然后所有请求打到数据库层导致数据库也挂了,这时该怎么进行恢复?

就以我三年的工作经验来说显然是超出了我的范围,没遇到过这样的场景,平时也没怎么想过,然后当时的第一思路就是先做限流,然后逐步恢复Redis和数据库。

很明显,当时这个问题我回答的并没有让面试官满意,但是实在所见有限,没有其他思路了,欢迎路过的朋友给一些其他思路。

2、Spring里面的bean id是否允许重复?如果允许重复的话重复了怎么办?如果不允许重复是怎么处理的?

因为在我的个人简历里面写了自己深入阅读过Spring源码的,所以这一个问题明显是就这一项的发问,当时自己确实记得是不允许重复的,所以回答的是不允许重复,如果重复了抛出bean重复定义的异常。然后面试官当场给我指出来说是允许重复的,如果重复了的话后加载进来的是覆盖前面的,不会做抛错。

针对这个问题,我重新翻阅了一下Spring源码,原来我记混淆了,会抛出异常的是beanDefinition,处理逻辑如下方法:

DefaultListableBeanFactory.registerBeanDefinition

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		// 删掉了一部分代码

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			// 删掉了一部分代码
		}

		// 删掉了一部分代码
	}

可以看出,beanDefinition重复是否会抛出异常也是结合配置来说的。而对于实例id重复,那么直接是覆盖了,如代码:

	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

当然,这个问题的前置还有Spring的bean生命周期系列,回答完后问到这里的。

3、G1对宿主机有什么要求?

这个当时回答不上来,然后也没找到什么有用的资料;

4、堆设置有什么注意事项?

留出可用空间的20%给元空间。


小米一面

1、手写Dubbo的加权随机算法

背景是我简历上面写了深入了解Dubbo,对Dubbo源码有深入了解,然后面试官就问出了这个问题。比较简单,写出的代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class WeightedRandom {

    private static Random random = new Random();

    public static void main(String[] args) {
        List<Node> list = new ArrayList();
        list.add(new Node("节点一(5)",5));
        list.add(new Node("节点二(3)",3));
        list.add(new Node("节点三(2)",2));
        for (int i = 0;i < 10000;i++) {
            Node cur = selected(list);
            // 统计操作
        }
        // 打印结果
    }

    private static Node selected(List<Node> list) {
        if (list == null || list.size() == 0) {
            return null;
        } else if (list.size() == 1) {
            return list.get(0);
        }
        int totalWeight = 0;
        boolean sameWeight = true;
        int firstWeight = 0;
        for (int i = 0;i < list.size();i++) {
            if (i == 0) {
                totalWeight += list.get(0).weight;
                firstWeight = list.get(0).weight;
            } else {
                totalWeight += list.get(i).weight;
                if (list.get(i).weight != firstWeight) {
                    sameWeight = false;
                }
            }
        }
        if (!sameWeight) {
            int curVal = random.nextInt(totalWeight);
            for (int i = 0;i < list.size();i++) {
                curVal -= list.get(i).weight;
                if (curVal < 0) {
                    return list.get(i);
                }
            }
        }

        return list.get(random.nextInt(list.size()));
    }

    private static class Node {
        String name;
        int weight;

        public Node(String name,int weight) {
            this.name = name;
            this.weight = weight;
        }
    }
}

2、Spring获取代理对象解决事务失效的问题。

调Spring对应的api,这样做会把框架代码耦合在自己的业务代码中;

自己注入自己,需要注意死循环的问题;

尽量避免这种同一个Service中非事务方法调用事务方法的情况。


滴滴二面

1、一个升序数组,随机选择一个旋转节点。右边的有序段放到左边,依然保持有序;左边的有序段放到右边,依然保持有序。然后从这个数组中查找某个数。

这个问题本质还是找那个旋转点,当知道那个旋转点后,无非就是在左边或者右边进行二分查找。

当时回答这个问题的主要思路就是从一个数组两头开始,分别作为left和right,然后计算中间位置mid,然后在left和mid之间找新的left,在mid和right之间找新的right,不断逼近从而找出那个旋转节点,旋转节点满足条件:arr[index - 1] > arr[index] > arr[index + 1]。


美团一面

1、Spring和Mybatis是怎么结合的?

这个问题当时没有理解面试官的意图,然后回答它们之间有一个整合包,这个整合包充当了一个适配器的角色,然后面试官就没有再问了。

2、mysql explain有哪些项?

常规问题,比如涉及的表、访问方法、可能索引、实际使用的索引等。

3、dubbo协议

这一个也是针对简历来问的,听到后心里有点凉快,然后就老实回答自己对于一些核心流程代码确实看过,但是对于这样底层的东西确实没有怎么了解过。

4、单链表找循环节点。

leetcode上的常规题了,几分钟就搞定了。


小米二面

1、顺序读取一亿个整数,找出前100万大的数字,内存限定大小为10M,后内存限定大小为5M。

我首先回答1个整型在内存中占4个字节,100万个整数占用4M,然后我在内存中加载200万个整数分为2个组,排序然后合并选出前100万大的数字,然后重新读取100万个数字继续同样的操作。

这时,面试官说将内存限制为5M。

很明显,就是想问问大顶堆而已,然后就回答使用大顶堆,毕竟返回结果不要求严格有序,只要前100万大就可以了。

小米二面面完后,还有三面的,但是我实在忍受不了那个三面面试官那牛逼哄哄的样子,所以面到一半我就直接退出会议室了,面了这么多场,遇到了一些态度很好的面试官,也遇到一些态度很差的面试官,就数小米这三面面试官的态度最他么恶心。

在小米三面的时候我就已经拿到自己想要的offer了,所以那天面试也就是抱着聊的好玩的心态聊,并没想去小米,结果着实把我恶心了。


去哪儿一面

1、stream和foreach区别?

有使用,但是没有太多了解,就没有回答出什么。

2、zookeeper和nacos区别?nacos符合CP还是AP?

这个问题印象特别深,原本是没有看过nacos官方对这一个介绍的,但是看过CAP理论,然后想到即使nacos挂了,nacos客户端仍然可以通过本地缓存列表继续工作,所以果断回答了AP。

posted @ 2021-07-26 14:27  小白先生哦  阅读(1624)  评论(11编辑  收藏  举报