經(jīng)過(guò)朋友內(nèi)推,終于獲得了百度的面試機(jī)會(huì), 這里主要介紹技術(shù)面試的內(nèi)容
技術(shù)面試主要分為兩輪面試,整體感覺(jué)百度面試的比較詳細(xì),很多細(xì)節(jié)方面的東西
技術(shù)面試通過(guò)以后,會(huì)有另外一個(gè)面試
百度的面試效率比較高,三輪面試總共持續(xù)了2天
第一輪面試
1. 簡(jiǎn)單介紹自己
這個(gè)沒(méi)什么說(shuō)的,主要都是從簡(jiǎn)歷上面說(shuō)一下,面試官也會(huì)根據(jù)簡(jiǎn)歷進(jìn)行提問(wèn)
2. 想象一個(gè)場(chǎng)景:一個(gè)系統(tǒng)要同步美國(guó)(訂單)和中國(guó)的數(shù)據(jù)(其余主要數(shù)據(jù)),通過(guò)太平洋海底光纜進(jìn)行傳輸,成本非常高。現(xiàn)在遇到了一些問(wèn)題,隨著數(shù)據(jù)量增加,無(wú)法在規(guī)定時(shí)間內(nèi)進(jìn)行同步,現(xiàn)在設(shè)計(jì)一種同步方式,達(dá)到目的(提示:MQ)。
- 開(kāi)多個(gè)端口,并行傳輸
- 通過(guò)專(zhuān)門(mén)的消息中間件(MQ)進(jìn)行生產(chǎn)者消費(fèi)者模式的數(shù)據(jù)推送和獲取
- MQ應(yīng)該部署在美國(guó),保證下單服務(wù)的平滑和正常
- 一致性方面,考慮使用MQ的回執(zhí)(Acknowledgment)來(lái)實(shí)現(xiàn)
3. threadlocal以及其應(yīng)用場(chǎng)景
- threadLocal是多線程的概念,主要指的是存儲(chǔ)于線程中的對(duì)象,屬于線程特有,同一個(gè)線程執(zhí)行的所有方法, 都可以獲取這部分?jǐn)?shù)據(jù)。
- threadLocal中的數(shù)據(jù)只能有本身的線程訪問(wèn),所以一般情況下, 這部分?jǐn)?shù)據(jù)是線程安全的
- hibernate中的thread-bind-session就使用了threadLocal,當(dāng)然還有其他實(shí)現(xiàn)
- spring的 OpenSessionInViewFilter 機(jī)制
4. 利用tomcat做過(guò)什么實(shí)現(xiàn)?jetty中的nio是怎么體現(xiàn)的?
jetty中,異步的配置主要體現(xiàn)在這里:
<Call name="addConnector">
<Arg>
<New class="org.mortbay.jetty.nio.SelectChannelConnector">
<Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>
<Set name="maxIdleTime">30000</Set>
<Set name="Acceptors">2</Set>
<Set name="confidentialPort">8443</Set>
</New>
</Arg>
</Call>
nio在異步請(qǐng)求模型中的作用主要是將模型的三大部分都通過(guò)異步的方式處理
- 偵聽(tīng)鏈接線程
- 偵聽(tīng)請(qǐng)求線程
- 數(shù)據(jù)處理線程
參見(jiàn)博客原文: <從Jetty、Tomcat和Mina中提煉NIO構(gòu)架網(wǎng)絡(luò)服務(wù)器的經(jīng)典模型>
主要應(yīng)用到的nio包結(jié)構(gòu)如下:
參見(jiàn)博客:<仿照jetty的nio原理寫(xiě)了個(gè)例子>
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector; // 起到阻塞的作用, selector.select()
import java.nio.channels.ServerSocketChannel; // 通過(guò)channel綁定到一個(gè)端口,
import java.nio.channels.SocketChannel; //
import java.util.concurrent.ConcurrentLinkedQueue; //兩個(gè)實(shí)例, 主要存放接收到的 鏈接 和 請(qǐng)求
主要監(jiān)聽(tīng)方法, 每個(gè)步驟都是一個(gè)線程去處理的, 主線程不會(huì)阻塞
public void listen() throws IOException { // 服務(wù)器開(kāi)始監(jiān)聽(tīng)端口,提供服務(wù)
channel.socket().bind(new InetSocketAddress(port)); // 將scoket榜定在制定的端口上
channel.configureBlocking(true);
new Thread(new ConnectionHander()).start();
new Thread(new RequestExecutor()).start();
new Thread(new RequestHander()).start();
}
對(duì)于nio相關(guān)的類(lèi)的解釋, 參見(jiàn)這個(gè)博客:<Java NIO API詳解>
5. 算法:一個(gè)數(shù)組中有多個(gè)整數(shù), 其中有兩個(gè)重復(fù)的數(shù)字,如何找出來(lái),考慮一下時(shí)間復(fù)雜度和空間復(fù)雜度
這個(gè)算法的解釋比較多
- 位圖法/Hash, 空間復(fù)雜度為n, 時(shí)間復(fù)雜度為n
- 先對(duì)數(shù)組排序, 然后再進(jìn)行遍歷, 時(shí)間復(fù)雜度>n
6. 系統(tǒng)優(yōu)化總共分為幾個(gè)部分?如何優(yōu)化?
7. Hash函數(shù)的概念
8. hash函數(shù)以及簡(jiǎn)單的應(yīng)用
9. OSGI模型, 以及其中的應(yīng)用
osgi指的是 Open Services Gatewag initiative,是一套java提供的一種更加抽象和封裝性的接口,有一些特性非常重要:
- 動(dòng)態(tài)性,可以動(dòng)態(tài)的升級(jí)模塊
- 基于接口編程,完全隱藏實(shí)現(xiàn)
- 提供了更加嚴(yán)格的模塊檢查,更加嚴(yán)格的一致性檢查
具體參見(jiàn)這個(gè)教程,需要登錄
第二輪面試
(不按照時(shí)間順序排列)
1. 白板編寫(xiě)程序: 生產(chǎn)者消費(fèi)者模型 或者 單例模型(主要考查單例的寫(xiě)法, 兩個(gè)判空)
作者選取了單利模型的編寫(xiě),單例以及其寫(xiě)法討論, 參見(jiàn)這個(gè)博客:《Java Notes 00 - Singleton Pattern(單例總結(jié))》
本來(lái)作者給出了內(nèi)部類(lèi)的答案,但是面試官還是偏向想看線程安全的寫(xiě)法
2. spring的事務(wù)是怎么實(shí)現(xiàn)的,嵌套場(chǎng)景下的aop實(shí)現(xiàn)
通過(guò)aop做代理實(shí)現(xiàn),但是需要強(qiáng)調(diào)的是:
- 一般場(chǎng)景下, 需要通過(guò)spring注入的方法才會(huì)代理,同一個(gè)類(lèi)內(nèi)部調(diào)用方法的話,是不會(huì)產(chǎn)生代理作用的
- 但是事務(wù)回滾的話,是通過(guò)異常去處理的??jī)?nèi)部方法拋出異常的話,會(huì)回滾嗎
- 推薦一個(gè)git:simpleApm
嵌套事務(wù)的話, 了解一下配置,會(huì)有一些概念 參見(jiàn)博客: <關(guān)于Spring嵌套事務(wù)>
- PROPAGATION_REQUIRED -- 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù)。這是最常見(jiàn)的選擇。
- PROPAGATION_SUPPORTS -- 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行。
- PROPAGATION_MANDATORY -- 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就拋出異常。
- PROPAGATION_REQUIRES_NEW -- 新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。
- PROPAGATION_NOT_SUPPORTED -- 以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
- PROPAGATION_NEVER -- 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
- PROPAGATION_NESTED -- 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒(méi)有事務(wù),則進(jìn)行與PROPAGATION_REQUIRED類(lèi)似的操作。
- 前六個(gè)策略類(lèi)似于EJB CMT,第七個(gè)(PROPAGATION_NESTED)是Spring所提供的一個(gè)特殊變量。
它要求事務(wù)管理器或者使用JDBC 3.0 Savepoint API提供嵌套事務(wù)行為(如Spring的DataSourceTransactionManager)
public void listen() throws IOException { // 服務(wù)器開(kāi)始監(jiān)聽(tīng)端口,提供服務(wù)
channel.socket().bind(new InetSocketAddress(port)); // 將scoket榜定在制定的端口上
channel.configureBlocking(true);
new Thread(new ConnectionHander()).start();
new Thread(new RequestExecutor()).start();
new Thread(new RequestHander()).start();
}
3. 描述一個(gè)項(xiàng)目及其架構(gòu)
4. ES的使用, 使用中有沒(méi)有做過(guò)數(shù)據(jù)量的測(cè)試
5. 數(shù)據(jù)庫(kù)調(diào)優(yōu)方面,有什么方法
- 主要先查看瓶頸在哪里,比如CPU,內(nèi)存,磁盤(pán)
- 根據(jù)業(yè)務(wù)的數(shù)據(jù)量,確定數(shù)據(jù)庫(kù)設(shè)計(jì)是否合理
- 使用工具捕獲執(zhí)行時(shí)間長(zhǎng)的語(yǔ)句,然后調(diào)優(yōu),根據(jù)業(yè)務(wù)場(chǎng)景查看語(yǔ)句寫(xiě)法是否恰當(dāng)
6. JVM中,Minor GC、Major GC和Full GC之間的區(qū)別
推薦一個(gè)博客:<hunter129>
7. JVM中,你遇到的內(nèi)存溢出是什么情況的,怎么發(fā)現(xiàn)的,怎么調(diào)查的,怎么修改的,如何保證后續(xù)的穩(wěn)定
java中, 針對(duì)jvm的狀態(tài)監(jiān)測(cè), 在windows的調(diào)試中, 最簡(jiǎn)單的也許是可視化工具 jvisualvm.exe
一般來(lái)說(shuō),通過(guò)jvisuavm可以比較方便的觀察jvm的所有情況,包括cpu、線程、內(nèi)存等
8. threadlocal的概念,線程安全的概念,synchronized的理解(這個(gè)關(guān)鍵字是鎖方法還是鎖對(duì)象)
坑爹的是, synchronized這個(gè)關(guān)鍵字整個(gè)是鎖對(duì)象的! 參見(jiàn)一篇文章 java同步設(shè)計(jì)敗筆
順便推薦一個(gè)公眾號(hào) 微信號(hào) iteedu 很少人知道, 但是很好
9. 線程的概念,使用多線程的場(chǎng)景是什么樣的?線程池是怎么實(shí)現(xiàn)的?(BlockQueue的概念)
線程是程序的實(shí)際工作者,不同于進(jìn)程,進(jìn)程更加偏向于資源的管理。跨線程之間的數(shù)據(jù)交換比較簡(jiǎn)單,但是跨進(jìn)程就會(huì)比較艱難。
使用多線程的場(chǎng)景往往是有等待的情況。等待可以來(lái)源于很多情況,比如cpu等待io,UI線程等待后臺(tái)線程等等。
多線程的正確使用, 往往會(huì)帶來(lái)硬件的充分利用。
但是多線程的使用, 往往也會(huì)帶來(lái)一些線程安全的問(wèn)題。
此時(shí)就需要充分利用鎖的概念。
10. 遇到了一個(gè)服務(wù),發(fā)現(xiàn)有性能問(wèn)題,如何在現(xiàn)有的機(jī)器之下做最大化的優(yōu)化?從哪些方面著手?
11. redis中的所有數(shù)據(jù)結(jié)構(gòu),redis是怎么用的?集群策略的話,需要考慮哪些東西,redis代理用過(guò)不?
redis集群策略
- 官方自帶 : redis-cluster 需要redis-3.0以上的版本
- 參見(jiàn)redis的官方文檔,這個(gè)集群的實(shí)現(xiàn),通過(guò)在redis中增加集群配置,然后每個(gè)節(jié)點(diǎn)都可以向任意節(jié)點(diǎn)發(fā)送請(qǐng)求
- 每個(gè)get和set操作都會(huì)事先進(jìn)行hash映射,然后到目的節(jié)點(diǎn)中執(zhí)行
- redis-cluster結(jié)構(gòu)圖
- 開(kāi)源的集群代理主要的實(shí)現(xiàn)有dynomite,twemproxy,codis
- 代理則不一致,代理主要面對(duì)的是另一種應(yīng)用場(chǎng)所
- twemproxy的部署圖
redis
12. springMVC的設(shè)計(jì)模式,都是做什么的? Controller是使用Servlet規(guī)范中哪個(gè)對(duì)象實(shí)現(xiàn)的?
Controller是使用filter實(shí)現(xiàn)的
13. spring事務(wù)的回滾機(jī)制,是怎么回滾的?子方法拋出異常的話,會(huì)回滾嗎?
事務(wù)回滾, 必須要拋出異常,異常要是被捕獲的話,事務(wù)是不會(huì)回滾的,這個(gè)要基于spring的事務(wù)實(shí)現(xiàn)機(jī)制進(jìn)行考慮。
14. redis的數(shù)據(jù)類(lèi)型,list和set的區(qū)別?
redis中5種數(shù)據(jù)類(lèi)型
- string, 主要的操作包括 get, set,incr,decr,mget以外, 還有一些其他操作
- 獲取字符串長(zhǎng)度
- append
- 設(shè)置和獲取字符串的某一內(nèi)容
- 設(shè)置和獲取某一bit
- 批量設(shè)置一系列字符串的內(nèi)容
- hash
- list 是一個(gè)雙向列表,主要有以下操作
- l操作,隊(duì)列的頭進(jìn)行操作
- r操作,隊(duì)列的尾操作
- bl操作, 阻塞式l操作
- set,本質(zhì)上是一個(gè)hashmap的實(shí)現(xiàn)
- sort set 有加權(quán)以后的hashmap實(shí)現(xiàn),根據(jù)權(quán)重 score來(lái)進(jìn)行排序
15. 說(shuō)說(shuō)NIO的概念,與普通IO有什么區(qū)別?
16. 數(shù)據(jù)復(fù)制,數(shù)據(jù)遷移方面是怎么做的?用什么工具?mysql的binlog是怎么應(yīng)用的?有什么開(kāi)源框架在使用這個(gè)特性?
binlog:參見(jiàn)這個(gè)介紹
第三輪面試
第三輪面試主要偏向?qū)θ说目疾椋热缈箟耗芰Γ瑢?duì)加班的看法,對(duì)百度的看法等。估計(jì)面試官不一樣,考查方式也不一樣。
面試官會(huì)比較偏重于第一映像,同時(shí)會(huì)察言觀色
1. 編寫(xiě)一個(gè)二分搜索的程序,一張紙,一支筆直接寫(xiě)
這個(gè)程序還是十分簡(jiǎn)單的,面試你官不僅會(huì)查看編寫(xiě)程序的結(jié)果,也會(huì)看著你編程,其中會(huì)測(cè)試你的抗壓能力
2. 對(duì)996加班機(jī)制怎么看?對(duì)年紀(jì)比較小,但是收入要更高的其他成員會(huì)怎么看?
3. 針對(duì)百度目前的輿論是怎么看的