小米 Java服务端开发

岗位描述

岗位职责:

1.参与小米公司级别平台后端服务, 负责项目建设与支持;

2.工作踏实负责,能积极有效与工作中的公司内部和外部合作方沟通;

3.持续服务优化, 负责建设高并发,高可用系统;

4.能调研和解决最终用户的实际问题;

5.参与服务端基础组件研发,核心架构建设, 负责技术调研,技术方案实施与研发;。

岗位要求

1、两年及以上后台服务器开发经验(有大型服务开发经验者优先);

2、精通Java编程,具备丰富的编程经验,能够熟练应用restlet/mybatis/spring等主流开发框;

3、熟悉分布式系统的设计和应用,熟悉分布式锁、NoSQL、消息队列等机制;

4、技术基础扎实,精通操作系统原理、数据结构、算法、网络编程和多线程编程等技术;

5、具备优秀的逻辑思维能力,善于分析和解决问题 ,对解决挑战性问题充满热情;

6、善于学习新知识,动手能力强,并有强烈的进取心。

面试过程

问题1:算法题

问:

给定包含n个整数的数组A,找到数组中每一个元素A左侧离它最近且小于该元素的整数数组下标,如果不存在返回-1;

样例1:
输入:
0 1 2 3 4 5
输出:
-1 0 1 2 3 4

样例2:
输入:
5 4 3 2 1 0
输出:
-1 -1 -1 -1 -1 -1

样例3:
输入:
4 8 7 9 10 5 3
输出:
-1 0 0 2 3 0 -1

答: 先说了n方的暴力方法,但是面试官提示说有o(N)的方法,所以继续网上找了找,是一个题的改编版

找出数组中每个数右边第一个比它大的元素--时间复杂度o(n)单调栈解法)

import java.util.Stack;

public class Main {

    public static int[] findMinLefttWithStack(int[] array) {
        if(array == null) {
            return array;
        }
        int size = array.length;
        int[] result = new int[size];
        Stack<Integer> stack = new Stack<>();
        stack.push(size-1);
        int index = size-2;
        while(index > -1) {
            if(!stack.isEmpty() && array[index] < array[stack.peek()]) {
                result[stack.pop()] = index;
            } else {
                stack.push(index);
                index--;
            }
        }
        while(!stack.isEmpty()) {
            result[stack.pop()] = -1;
        }
        return result;
    }
    public static void main(String[] args) {
        int[] array ={4,8,7,9,10,5,3};
        int [] result=findMaxRightWithStack(array);
        for(int i=0;i<array.length;i++){
            System.out.print(array[i]+ " ");
        }
        System.out.println( "");
        for(int j=0;j<array.length;j++){
            System.out.print(result[j]+ " ");
        }

    }
}

先问了什么时候毕业,然后自我介绍,说了实验室项目

问题2:编程语言基础

问:Go语言什么时候开始接触的

答:研究生进入实验室开始了解的,最近找工作看java多一点

问:Go语言的特性有深入了解过吗,和java有啥区别

答:了解过,Go语言最大的特点就是并发性好一点,但是实验室项目没怎么用到(此时面试官要强行插话切入到并发话题,被我夺过来话了,并发没深入看,聊不下去)。Go的方法只能是唯一命名,没有重载重写。java是纯面向对象的,有重载重写。

问:就是没有泛型

问:java经验有没有

答:java没有相关web开发经验

问:问了本科,问了专业,问了本科学习时间

答:balabala

问:我们部门用java,我们有项目也会用到一些Go,正在尝试,但是还没有用起来。Go的有些问题问下:go里面有个channel的东西

答:知道,没用过

问:了解defer的用法吗

答:呃...不知道,没听说过

问:defer这个词没听说过吗,很常见的

答:哪部分的?

问:一般就是先加把锁,然后defer,然后unlock一下

答:go语言的锁吗

问:对的呀,很常见

问:java里面的多线程,你了解的多吗。 java里面有个锁通道,synchroniza关键字,volatile关键字,锁的优化,简述下synchroniza的过程是一个什么样子的吗

答:synchroniza修饰方法,synchroniza修饰代码块,synchroniza修饰实例对象。

synchroniza修饰实例对象。就把对象锁住了

synchroniza修饰静态方法,就把类给锁住了

问:听说过偏向锁/轻量级锁,可重入锁这些概念吗

答:锁的种类,有公平锁/非公平锁,可重入锁,独享锁/共享锁,互斥锁/读写锁,乐观锁/悲观锁,分段锁,自旋锁

问:jvm对synchroniza底层做了一个优化,实现过程中会有一个锁通道的过程,想问的是锁通道的过程具体是一个什么样子的。

答:呃.....

问:公平锁/非公平锁是一个什么概念

答:公平锁是指多个线程按照申请锁的顺序来获取锁。非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序

问:不是按照申请锁的顺序,是按照什么顺序获取

答:呃.........(随便说了一点)有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。

问:比如说ReentrantLock,它的实现大概是一个什么样子的,原来是非公平的,怎么就公平了

答:呃....

问:可重入锁是一个什么概念

答:在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁

问:内部随便一个方法都可以吗,还是说有一个限制条件

答:e....不清楚

问:比如说我现在获取到了一把锁,然后里面开了一个线程,新开了一个线程,然后还想获取一把锁,但是子线程并没有释放它,那它可以吗

答:e...会等待

问:为什么要等待了

答:e.....

问:hashmap和treemap内部结构大致是什么样子,具体是一个什么样的数据结构

答:hashmap balabal 数据和链表 value长度》=8链表转红黑树

​ treemap 有序 balabal

问题3:操作系统

问:操作系统里面有个虚拟内存,解释一下,它的作用是什么,还有就是为什么会有虚拟内存这个东西

答:e.....

问:进程和线程的区别

答:进程里面有好多的线程,线程是操作系统进行调度的基本单位。一个程序至少有一个进程,一个进程至少有一个线程。

问:线程有哪几种状态,以及几种状态中的转换关系是什么

答:开始,可运行,阻塞,等待,定时等待,终止

问:什么情况会进行状态转换说一下

答:e...

  • 开始(New) - 还没有调用 start() 方法的线程处于此状态。
  • 可运行(Runnable) - 已经调用了 start() 方法的线程状态。此状态意味着,线程已经准备好了,一旦被线程调度器分配了 CPU 时间片,就可以运行线程。
  • 阻塞(Blocked) - 阻塞状态。线程阻塞的线程状态等待监视器锁定。处于阻塞状态的线程正在等待监视器锁定,以便在调用 Object.wait() 之后输入同步块/方法或重新输入同步块/方法。
  • 等待(Waiting) - 等待状态。一个线程处于等待状态,是由于执行了 3 个方法中的任意方法:Object.wait()``Thread.join()``LockSupport.park()
  • 定时等待(Timed waiting) - 等待指定时间的状态。一个线程处于定时等待状态,是由于执行了以下方法中的任意方法:Thread.sleep(sleeptime)``Object.wait(timeout)``Thread.join(timeout)``LockSupport.parkNanos(timeout)``LockSupport.parkUntil(timeout)
  • 终止(Terminated) - 线程 run() 方法执行结束,或者因异常退出了 run() 方法,则该线程结束生命周期。死亡的线程不可再次复生。

问:操作系统里面有一个死锁的概念,死锁具体是由什么产生的,然后会有什么解决方法

答:多个线程互相等待对方释放锁。死锁是当线程进入无限期等待状态时发生的情况,因为所请求的锁被另一个线程持有,而另一个线程又等待第一个线程持有的另一个锁。

​ 避免一个线程同时获取多个锁;避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源;尝试使用定时锁 lock.tryLock(timeout),避免锁一直不能释放;对于数据库锁,加锁和解锁必须在一个数据库连接中里,否则会出现解锁失败的情况。

问题4:数据库

问:关于数据库这块,你说到了mongodb,还用过其他的数据库吗

答:sql server

问:那索引类型都有哪些

答:聚集索引和非聚集索引,

问:那什么是聚集索引,什么是非聚集索引

答:聚集索引,数据按索引顺序存储,子结点存储真实的物理数据 。索引的叶节点就是数据节点

​ 非聚集索引,叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。

问:mysql里面有一个很重要的概念,叫做 jianxvsuo,听说过吗

答:呃....没听说

问题5:网络

问:简述一下TCP里面的三次握手,四次挥手

答:第一次握手 - 客户端向服务端发送带有 SYN 标志的数据包。第二次握手 - 服务端向客户端发送带有 SYN/ACK 标志的数据包。第三次握手 - 客户端向服务端发送带有带有 ACK 标志的数据包。

第一次挥手 - 客户端向服务端发送一个 FIN 包,用来关闭客户端到服务端的数据传送。第二次挥手 - 服务端收到这个 FIN 包,向客户端发送一个 ACK 包,确认序号为收到的序号加 1。和 SYN 一样,一个 FIN 将占用一个序号。第三次挥手 - 服务端关闭与客户端的连接,向客户端发送一个 FIN 包。第四次挥手 - 客户端向服务端发送 ACK 包,并将确认序号设置为收到序号加 1。

问:那如果四次挥手最后一个包没有收到,会出现什么情况

答:额.....

问;http常见的状态码你了解过吗

答:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它 URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误
1 信息,服务器收到请求,需要请求者继续执行操作
2 成功,操作被成功接收并处理
3 重定向,需要进一步的操作以完成请求
4 客户端错误,请求包含语法错误或无法完成请求
5 服务器错误,服务器在处理请求的过程中发生了错误

问: 那302 是什么状态

答:e....

问:那http常见的方法有哪些

答:

方法 描述
GET 请求指定的页面信息,并返回实体主体。
HEAD 类似于 get 请求,只不过返回的响应中没有具体的内容,用于获取报头
POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
PUT 从客户端向服务器传送的数据取代指定的文档的内容。
DELETE 请求服务器删除指定的页面。
CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。

以下为面试准备

流程猜测

  • 自我简介
  • 项目中遇到的最大的难题,怎么解决的
  • 谈谈你对小米的认识
  • java 和go的区别
  • mysql 和mongodb的区别
  • 设计一个秒杀系统

他山之石

数据结构与算法

你所知道的排序算法有哪些,哪些是基于比较的

排序算法

  • 基于比较的排序
    • 堆排序
    • 选择排序 插入排序 冒泡排序

时间复杂度和空间复杂 稳定性

快排的步骤,你认为最关键的一步是哪个,最差情况的时间复杂度

写快拍

再写个快排非递归

递归会出现什么问题

讲桶排序,桶排序为什么是稳定的,桶排序维持稳定是否需要额外空间

二叉树遍历

java二叉树遍历——深度优先(DFS)与广度优先(BFS) 递归版与非递归版

二叉树层级遍历 同时输入层数

你所知道的数据结构有哪些?

讲一下什么是B 树

讲一下红黑树,插入数据时怎么判断红黑树是否平衡

红黑树

一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1

输出一个数组中某元素出现的次数超过数组长度一半的元素,没有则输出null。

二叉搜索树的 two sum 问题

链表反转

算法:链表1->2->3>4反转为1>4>2>3。

二分查找

二叉树公共父节点

n个新字符串插入到一个源字符串的指定位置。比较简单,实现的时候和面试官讨论了一波算法复杂度问题

给一个数列,输出top k

javacore

基础

数组链表区别

  • 数组

    一、数组的特点 1.在内存中,数组是一块连续的区域 2.数组需要预留空间

    在使用前需要提前申请所占内存的大小,这样不知道需要多大的空间,就预先申请可能会浪费内存空间,即数组空间利用率低 ps:数组的空间在编译阶段就需要进行确定,所以需要提前给出数组空间的大小(在运行阶段是不允许改变的)

    3.在数组起始位置处,插入数据和删除数据效率低。

    插入数据时,待插入位置的的元素和它后面的所有元素都需要向后搬移 删除数据时,待删除位置后面的所有元素都需要向前搬移

    4.随机访问效率很高,时间复杂度可以达到O(1)

    因为数组的内存是连续的,想要访问那个元素,直接从数组的首地址处向后偏移就可以访问到了

    5.数组开辟的空间,在不够使用的时候需要扩容,扩容的话,就会涉及到需要把旧数组中的所有元素向新数组中搬移 6.数组的空间是从栈分配的

    二、数组的优点 随机访问性强,查找速度快,时间复杂度为O(1)

    三、数组的缺点 1.头插和头删的效率低,时间复杂度为O(N) 2.空间利用率不高 3.内存空间要求高,必须有足够的连续的内存空间 4.数组空间的大小固定,不能动态拓展

  • 链表 一、链表的特点 1.在内存中,元素的空间可以在任意地方,空间是分散的,不需要连续 2.链表中的元素都会两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址

    每一个数据都会保存下一个数据的内存的地址,通过此地址可以找到下一个数据

    3.查找数据时效率低,时间复杂度为O(N)

    因为链表的空间是分散的,所以不具有随机访问性,如要需要访问某个位置的数据,需要从第一个数据开始找起,依次往后遍历,直到找到待查询的位置,故可能在查找某个元素时,时间复杂度达到O(N)

    4.空间不需要提前指定大小,是动态申请的,根据需求动态的申请和删除内存空间,扩展方便,故空间的利用率较高 5.任意位置插入元素和删除元素效率较高,时间复杂度为O(1) 6.链表的空间是从堆中分配的

    二、链表的优点 1.任意位置插入元素和删除元素的速度快,时间复杂度为O(1) 2.内存利用率高,不会浪费内存 3.链表的空间大小不固定,可以动态拓展

    三、链表的缺点 随机访问效率低,时间复杂度为0(N)

  • 对于想要快速访问数据,不经常有插入和删除元素的时候,选择数组
    对于需要经常的插入和删除元素,而对访问元素时的效率没有很高要求的话,选择链表

StringBuild和StringBuffer的区别

接口和抽象类的区别

抽象类(abstract-class)与接口(interface)有什么异同

讲解继承与组合的区别

谈谈volatile关键字

重载和重写的区别

const的用法,const多态原理

容器

HashSet 的底层实现

聊JAVA的集合set,set怎安实现允许重复的

hashMap底层实现

stl 中set map底层实现,与hashtable的差异,使用情况。

多线程

多线程,线程池,四中线程池。

java中怎么创建 一个线程

2.2. 创建线程有哪些方式?这些方法各自利弊是什么?

如何实现java多线程

  1. 继承Thread类,重写run()方法
  2. 实现Runnable 接口,并实现该接口的run()方法

run()方法和start()方法的区别

start()run() 有什么区别?可以直接调用 Thread 类的 run() 方法么?

线程怎么同步?

多线程同步的实现方法有哪些

  1. synchronized关键字

    在Java语言中,每个对象都有一个对象锁与之相关联,该锁表明对象在任何时候只允许被一个线程所拥有,当一个线程调用对象的一段synchronized代码时,需要先获取这个锁,然后去执行相应的代码,执行结束后,释放锁。synchronized关键字有两种用法,synchronized方法和synchronized块。该关键字还可以作用于静态方法、类或某个实例。

​ 1.1 synchronized方法,在方法的声明前加入synchronized关键字。

​ 1.2 synchronized块,既可以把任意的代码段声明为synchronized,也可以指定上锁的对象,有非常的灵活性。

  1. wait( ) 方法 与 notify( ) 方法

  2. wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

  3. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
  4. notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
  5. Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

  6. Lock

    JDK5新增加了Lock接口以及它的一个实现类ReentranLock,Lock也可以用来实现多线程的同步。

    ​ ❶lock()。以阻塞的方式获取锁,如果获取到了锁,立即返回;如果别的线程持有锁,当前线程等待,直到获取锁后返回。

    ​ ❷tryLock()。以非阻塞的方式获取锁。只是尝试性地去获取一下锁,如果获取到锁,立即返回true,否则,立即返回false。

    ​ ❸tryLock(long timeout, TimeUnit unit)。如果获取了锁,立即返回,否则会等待参数给定的时间单元,在等待的过程中,如果获取了锁,就返回true,如果等待超时,返回false。

    ​ ❹lockInterruptibly()。如果获取了锁,立即返回,如果没有获取锁,当前线程处于休眠状态,直到获得锁,或者当前线程被别的线程中断(会受到InterruptedException异常)。它与lock()方法最大的区别在于如果lock()方法获取不到锁,会一直处于阻塞状态,且会忽略interrupt()方法。

synchronized具体怎么用?能给什么对象上锁?

对象锁锁住的是,同样由synchronized修饰的方法或代码段。当然,这里排除了类锁。

Lock和synchronized的区别?它们都是可重入锁吗?哪个效率更高?

java并发之Lock与synchronized的区别)

当需要以下高级特性时,才应该使用Lock:可定时的、可轮询的与可中断的锁获取操作,公平队列,或者非块结构的锁。否则,请使用synchronized。

锁有哪几种?可重入锁和不可重入锁的区别?

多线程中锁的种类

虚拟机

jvm了解吗?说一下你了解的jvm

说说JVM,内存区。

jvm启动的底层是怎么实现的

类装载机制了解吗?怎么实现的

输入输出io

javaweb

websocket在聊天室中的使用方式

Spring的 IOC原理

SpringMVC请求流程)

二面问了事务的实现原理(redo+undo),

MVCC,引擎之间的区别,

项目中用到了MapReduce,讲一下map和reduce的过程

数据库

谈谈对数据库索引的理解

frank-lam 索引

从SQL优化角度谈谈索引

索引的数据结构,

b和b+的区别

左右连接

又问了数据库语句,第一个是查询分组计数,第二个是数据量大的时候使用limit分页,越往后查询越慢,怎么优化查询?

操作系统

进程间的通信方式

linux

Linux管道的作用

linux 常用指令介绍,chmod命令权限修改解释下

网络通信

(TCP该问的都问了)

三次握手,四次挥手

http中get与post的区别

http状态码有哪几种 HTTP 状态码

在浏览器中输入一个网址,浏览器的处理过程,涉及哪些层,用了哪些协议?

如果上面的是基于HTTPS的请求,会增加哪些流程呢(即HTTPS请求的流程)。HTTPS里面的对称加密的密钥是怎么发送的,能用RSA的私钥加密比它大的数据吗?

tcp和udp的区别

tcp的三次握手和四次挥手,

TCP滑动窗口

协程?(没听说过)

慢开始和拥塞控制原理,

设计模式

设计模式之单例模式

results matching ""

    No results matching ""