Current Position - Senior Software Engineer

Senior Java Engineer技术面试

面试时间: 90分钟
形式: 线上面试
面试结果:通过/拿到Offer

由于我还在这儿上班~我就不说是哪家公司了
整个流程为HR沟通->技术面试->成都Office Engineer head面试-> Engineer Head offer沟通。
Offer薪资范围参考招聘软件上的最高的那个范围。固定13薪+project/personal bonus, 但2种bonus说是可以忽略不计。
谈薪资时表示在上家的base基础上涨20%是很合理的,我开口就答应了,感觉我要低了。
面试中除了HR之外,所有面试上来就是英文,基本看英文ok之后会切换中文。
技术面试计划1小时,实际使用1小时47分钟。
面试深度不深,但广度较广,包含Java基础至微服务、分布式所有常见问题,以及一些敏捷、工程管理方法论,和实操经验,最后有一道在线编程题。

以下是我回忆的大致内容,用什么语言问的就用什么语言写的。

Q1: Could you talk about difference btw ArrayList and LinkedList

ArrayList is an array. It is fast for random visit because it has index for elements.The disadvantage of array is that it needs continuous memory area and it is more difficult for expansion because all indexes need to be calculated once you insert/delete any element.
LinkedList is fast for element update because it only needs to break/point links between the certain nodes. It does not require a continuous memory area. However the disadvantage is that it is difficult for element search because linkedlist always needs to search from the first node

Q2: What are the oops concepts?

The main 3 OOPS concepts are:

  1. Abstraction

Abstraction means hidding the details of items and describing items in simple / common terms. For example we say there is a car rather than there is a red card.

  1. Ecapsulation

Ecapsulation means hidding the details of an object and explore interface which I want to explore to the outside.

  1. Polymorphism

Polymorphism means that for the same object, it can behave in different ways in different situations.

Q3: Can you talk about IOC and AOP?

IOC is short for inversion of control which means that the implementation is controlled by abstract level rather than details or certain items. In Spring framework IOC is implemented by Dependency Injection(DI). DI means we only needs to declare an abstract interface/class and the implementation will be injected in runtime. The porpuse of IOC/DI is decoupling.
AOP is short for Aspect Oriented Programming. It is an extension of OOP. The target of OOP is object while the target of AOP is aspect which means edges between objects/methods/modules.

Q4: You talked about Spring so how many types of AOP you know in Spring?

There’re 4 types of AOP in Spring:
Dynamic proxy - Spring uses JDK proxy for interfaces and CGLib for classes
Java Object AOP -
@Aspect annotation - TODO

Q5: How many types of advice you know in Spring?

我回答的比较抽象,我跟他说了一下我们自己做框架的时候做切口的思路
6 types of advice in Spring:
1.Before
2.After
3.Around
4.After Returning
5.After throwing
6.DeclareParents

Q6: What are Spring bean scopes?

  1. Singleton
  2. Prototype
  3. global session
  4. request

Q7: What’s the difference btw REQUIRED_NEW and nested transaction in Spring transaction?

REQUIRED_NEW means start a brand new transaction everytime.

Q8: What does Spring MVC do when it receives a request from client?

Request - > DIspatcherServlet - > handler - > model view / rest data - > client.

Q9: What’s the difference between Controller and RestController?

Controller will find a model view and render while restcontroller directly write result into response body.

Q10: What is the volatile keyword and how it works?

Volatile is a key word for fields.
It is a simple synchronization tool.
Volatile has 2 functions:

  1. prevent JVM from
  2. force threads to read content from direct memory.

Q11: What design patterns you prefer and why?

I prefer Pipeline cuz it is stupid but easy to understand.It can clearly define how the program works step by step. In Spring there’s pipelines such as request handling pipeline, exception handling pipeline, security chain, etc..
Besides I like command and stratege mode because they can help you avoid writting lots of stupid if/else blocks. There’re lots of use case of command/stratege in workflow engines such as Floable/Camunda.

Q12: You said command and stratege so what’s the difference?

Command is focus on the command itself that you main code is to construct a context of a command.
Stratege is not focus on the context. It focus on stratege itself which means the function logic.

Q13: How do you find / tract an issue in a project, for example, a project composed by hundres of miscroservices?

My method is..
1st step, find which area the issue located. The area means network/application/service.
2nd, for example, I’ve found the application/service

Q14: How do you organize the network structure of an microservice project?

Q15: What is the biggest challenge in your work?

Q16: How do you like microservice?What’s the difference for you?

it brings a better business / structure understanding to team members but also more difficult to maintain.

Q17: 你是怎么理解Restful的

请自行百度

Q18: HashMap和ConcurrentHashMap有什么不同?

java8中两者实现基本相同,ConcurrentHashMap在修改相关的方法上,使用了synchronized关键字,因此ConcurrentHashMap是线程安全的map.
在java8之前,ConcurrentHashMap内部是分段map的形式,在每一段上使用ReetrantLock以达到线程安全的目的。

Q19: 可以说以下HashMap的put方法都做了什么吗?

详见源码,幸好中文问的要不还说不清楚

  1. HashMap使用自己实现的Hash方法,计算得到Key的hash值
  2. 检查内部的Node节点数组(可称作哈希槽)是否为空,如果为空,调用resize方法进行初始化(resize也负责扩容)
  3. 扩容的逻辑:如果哈希槽为空,先创建一个默认初始长度为16的数组;如果哈希槽已经初始化,检查是否达到扩容阈值,默认为0.75*当前长度,如果达到了,扩容为当前2倍
  4. 接下来继续走put流程,通过(n-1)&hash 计算出元素该位于哈希槽的哪个位置,其中n为当前哈希槽长度,hash为HashMap计算出的key的hash值, 如果该位置上没有东西,直接创建个Node放在这里
  5. 如果发现此处已有Node,开始判断是否重复,如果此处的Node的hash和key值,和要put的key的hash值和本身的值均相同,那么就认为是重复元素,直接返回。
  6. 如果发现此处已有Node, 但是并非重复,如果是TreeNode, 即链表已转化为红黑树,此时往红黑树中插入元素
  7. 如果发现此处已有Node, 但是并非重复,如果不是TreeNode, 即此时还是链表,先将元素插入到链表尾,再调用treeifBin方法,判断如果哈希槽长度小于64,先尝试resize扩大哈希槽;如果哈希槽长度小于64,切链表长度超过8,将链表转化为红黑树。
  8. 最后再判断,如果当前Map容量超过75%, 即0.75*当前容量, 再resize一次

Q20: 什么是堆

堆是JVM内存模型中,线程间共享的内存区域,其在逻辑上连续,在物理上不连续。我们创建的对象本身就放在堆中。

Q21: String s1 = new String(“1”); String s2 = new String(“2”); s1和s2有什么区别?

“1”和”2”在堆中(1.8之前在方法区)的字符串常量池里;
new的2个String对象在堆中
s1,s2 两个引用是在栈当中,指向堆中的2个String对象.

Q22: 在生产环境上你是如何处理jvm内存问题的?

加参数,oom的时候打dump
分析dump,查看发生问题的地方的代码
调整gc

Q23: 说一说几种垃圾回收算法

8之前默认是CMS算法
8开始默认是g1算法
11开始是zgc
具体请自行百度

Q24: 如果一句SQL效率有问题,你是如何分析的?

首先第一步,看表建的有没有问题,例如高低频字段要分开,外键是否对效率产生了影响
第二步,查看sql的执行计划,找出慢的步骤
第三步,看有没有建立相关索引,或者出现索引失效的问题,并且修复
第四步,可以使用mysql或者oracle的工具,sql advisor自动优化sql.

Q25: 你和你的team member在design上出现分歧的时候,你是如何解决的?

PS: 可能有相关的管理方法论,但是我不知道,我是这么回的:
在我担任TL的一开始时,当我遇到这种情况时,首先我会召开讨论,向其它说说明我的思路,尝试说服他人,或者别人有更好的,可信的方式,我会接受意见并共同作出修改。当僵持不下时,我会引入第三方加入讨论,例如architect。后来我在流程上做了一点点优化,在出design之前,会有design idea的事先沟通,将流程打碎。

Q26: 你是如何对工作量进行评估的?

我对工作量的估算有2个前提,第一我们知晓常规职级的工程师在单位时间内能完成的工作量,称作1个point, point同时应当表征任务难度;第二,我自己应知晓我的组员在单位周期内能完成的point量,通过以上两点,我可以估算出任务量以及任务完成进度,之后再加上一些buffer, 得出组内大概的任务燃尽图。

Q27: 你知道T-shirt size估算方法吗?

我回的不知道,确实不知道。
后面百度了一下,大概跟估算工作的方法差不多,t-shirt有自己的size, 我有自己的body size, 做match.

Q28: 怎样创建一个SpringBoot Starter

Q29: 你用过哪些微服务的组件,它们是做什么的?

我只用过Spring Cloud/Netflix/Spring Cloud Alibaba就挨着说一遍.
服务发现与配置:Nacos / Eureka / ZooKeeper
网关:SpringCloud Gateway / Zuul
限流:Hystrix / Sentinel
客户端: OpenFeign
客户端负载均衡:Ribbon / Spring Load Balancer
分布式事务:seata

Q30: 一套全新的微服务系统,你如何规划它的网络?

Q31: 你刚才提到外部的负载均衡,在它外面还有什么?

Q32: 你在项目中是如何使用RedisCluster的?

Q33: MongoDB是AP还是CP?

我回答的不知道,真的不知道,实际上并没有Mongo的生产经验,没有关注
百度了一下,在默认情况下,Mongo是CP的。

Q34: 你在项目中是如何做CI/CD的?

Q35: 你在什么场景下使用Docker?

Q36: 我看你使用过RabbitMQ, 是在什么场景下使用的呢?它和Kafka的区别是什么?

RabbitMQ是轻量级的消息队列,一般用作需要异步处理的情况,例如削峰,执行次要任务等,但是一般简单的情况下我会使用Redis的list来实现简单消息队列。
Kafka是流式处理中间件,由于其自身设计,其性能远高于RabbitMQ, 可用做消息队列,但大多情况下用于做流式的数据处理。

Q37: Coding: Create three threads to add data into Array from a Queue in sequence.

3个线程轮流从queue中取数放入数组,无非是考:

  1. 多线程同步,达到轮流效果
  2. 线程安全的2个容器,一个queue一个数组

我用的CyclickBarrier,之前网上看到过,其它实现方法很多

从网上反馈来看,java开发会考一些简单算法如排序遍历和一些二分思想,用的一个在线编程平台写或者是选择题选代码片段
senior java一般是多线程题,但都不是很复杂
我是叫我直接共享屏幕打开摄像头看着我写的,写完后将代码复制给他。
我是想起之前看到的一个 CyclicBarrier ,就直接写了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
* TI-coding
* Author: Jarry Zhou
* Date: 2022/3/28
* Description: Create three threads to add data into Array from a Queue<Integer> in sequence.
**/
public class Test {
public static void main(String[] args) {
BlockingQueue<Integer> q = new LinkedBlockingQueue<>();
q.offer(1);
q.offer(2);
q.offer(3);
q.offer(4);
q.offer(5);
AtomicInteger index = new AtomicInteger(0);
CyclicBarrier b1 = new CyclicBarrier(2);
CyclicBarrier b2 = new CyclicBarrier(2);
CyclicBarrier b3 = new CyclicBarrier(3);

new Thread(() -> {
while (!q.isEmpty()) {
try {
Optional.ofNullable(q.poll()).ifPresent(val -> {
final int idx = index.getAndIncrement();
System.out.println(Thread.currentThread().getName() + " puts " + val + " into index " + idx);
});
b1.await();
b3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();

new Thread(() -> {
while (!q.isEmpty()) {
try {
b1.await();
Optional.ofNullable(q.poll()).ifPresent(val -> {
final int idx = index.getAndIncrement();
System.out.println(Thread.currentThread().getName() + " puts " + val + " into index " + idx);
});
b2.await();
b3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();

new Thread(() -> {
while (!q.isEmpty()) {
try {
b2.await();
Optional.ofNullable(q.poll()).ifPresent(val -> {
final int idx = index.getAndIncrement();
System.out.println(Thread.currentThread().getName() + " puts " + val + " into index " + idx);
});
b3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();

}
}

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧

微信