小米 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 ""