大家好,我是小林。
早在 9-10 月份,華為就開展校園招聘了,面試面完之后, 就會進入池子,等待開獎,這一等就是 2 個月,很多同學(xué)糾結(jié)是等華為,還是先簽別的,擔(dān)心華為開不出來。
不過,華為的池子確實還是比較深的,基本上學(xué)歷對味,面試不要太拉跨,基本上都能面試通過之后進入池子。
泡池子的 ,中途可能還會收到 hr 的保溫電話,所謂保溫行為,是指通過面試后,到最后發(fā)offer之前,HR會不時地給通過了面試的求職者打電話,示意可能有offer,先不要簽其他家,你排名很還不錯,拿到華為 offer 的希望很大。
現(xiàn)在來到了 11 月底,華為最近開始陸陸續(xù)續(xù)開獎了,不少同學(xué)跟我爆料了華為的開獎情況。
我在這里也給大家整理了 25 屆華為校招開發(fā)崗的薪資情況,跟去年沒什么變化。
13 級別:19-21k * (14-16),年包 30~33w14 級別:22-25k * (14-16),年包 35~40w15 級別:26-31k * (14-16),年包 41~50w
華為的薪資主要根據(jù)職級來定的,校招開發(fā)崗位職級一般是 13級、14 級、15 級,再細節(jié)一點,還會分 14a,14b,14c。14 a 是 14 級別里面薪資最高的水平,14c 則是 14 級別里面的普通檔的薪資水平。
本科生基本是 13 級別,碩士生是 14 級別居多,個別比較優(yōu)秀的碩士能拿到 15 級別。
華為面試流程總共是 2 輪技術(shù)面+1 輪 hr 面,在約面之前,還得先進行機試,基本都是算法題,達到150分就算機試通過,然后就進行后面的技術(shù)面試。
華為的面試難度相比互聯(lián)網(wǎng)公司會簡單一點,不會問太深的技術(shù)原理,問的題目也不會很多,大概都是 10 -20 個問題,相比互聯(lián)網(wǎng)大廠一場面試動不動就問 30 個問題,確實壓力相對小一點。
今天給大家分享一位校招同學(xué)華為二面的面經(jīng),面試者的技術(shù)棧是Java,主要問了Spring、Java集合、并發(fā)、網(wǎng)絡(luò)、mysql 方面的問題,并且還有手撕算法的過程。
八股
Spring中的事務(wù)的隔離級別有哪些?
Sping 中的事務(wù)隔離級別有 5 種,它們分別是:
-
- DEFAULT:
Spring 中默認的事務(wù)隔離級別,以連接的數(shù)據(jù)庫的事務(wù)隔離級別為準;READ_UNCOMMITTED:讀未提交,也叫未提交讀,該隔離級別的事務(wù)可以看到其他事務(wù)中未提交的數(shù)據(jù)。該隔離級別因為可以讀取到其他事務(wù)中未提交的數(shù)據(jù),而未提交的數(shù)據(jù)可能會發(fā)生回滾,因此我們把該級別讀取到的數(shù)據(jù)稱之為臟數(shù)據(jù),把這個問題稱之為臟讀;READ_COMMITTED:讀已提交,也叫提交讀,該隔離級別的事務(wù)能讀取到已經(jīng)提交事務(wù)的數(shù)據(jù),因此它不會有臟讀問題。但由于在事務(wù)的執(zhí)行中可以讀取到其他事務(wù)提交的結(jié)果,所以在不同時間的相同 SQL 查詢中,可能會得到不同的結(jié)果,這種現(xiàn)象叫做不可重復(fù)讀;REPEATABLE_READ:可重復(fù)讀,它能確保同一事務(wù)多次查詢的結(jié)果一致。但也會有新的問題,比如此級別的事務(wù)正在執(zhí)行時,另一個事務(wù)成功的插入了某條數(shù)據(jù),但因為它每次查詢的結(jié)果都是一樣的,所以會導(dǎo)致查詢不到這條數(shù)據(jù),自己重復(fù)插入時又失?。ㄒ驗槲ㄒ患s束的原因)。明明在事務(wù)中查詢不到這條信息,但自己就是插入不進去,這就叫幻讀 (Phantom Read);SERIALIZABLE:串行化,最高的事務(wù)隔離級別,它會強制事務(wù)排序,使之不會發(fā)生沖突,從而解決了臟讀、不可重復(fù)讀和幻讀問題,但因為執(zhí)行效率低,所以真正使用的場景并不多。
所以,相比于 MySQL 的事務(wù)隔離級別,Spring 中多了一種 DEFAULT 的事務(wù)隔離級別。針對不同的隔離級別,并發(fā)事務(wù)時可能發(fā)生的現(xiàn)象也會不同。
也就是說:
- 在「讀未提交」隔離級別下,可能發(fā)生臟讀、不可重復(fù)讀和幻讀現(xiàn)象;在「讀提交」隔離級別下,可能發(fā)生不可重復(fù)讀和幻讀現(xiàn)象,但是不可能發(fā)生臟讀現(xiàn)象;在「可重復(fù)讀」隔離級別下,可能發(fā)生幻讀現(xiàn)象,但是不可能臟讀和不可重復(fù)讀現(xiàn)象;在「串行化」隔離級別下,臟讀、不可重復(fù)讀和幻讀現(xiàn)象都不可能會發(fā)生。
Spring事務(wù)的傳播行為有哪些?
在Spring中對于事務(wù)的傳播行為定義了七種類型分別是:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。
支持當(dāng)前事務(wù)的:REQUIRED、SUPPORTS、MANDATORY;不支持當(dāng)前事務(wù)的:REQUIRES_NEW、NOT_SUPPORTED、NEVER,以及嵌套事務(wù) NESTED,其中 REQUIRED 是默認的事務(wù)傳播級別。
事務(wù)傳播行為類型 | 說明 |
---|---|
PROPAGATION_REQUIRED | 如果當(dāng)前沒有事務(wù),就新建一個事務(wù),如果已經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中。這是最常見的選擇。 |
PROPAGATION_SUPPORTS | 支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。 |
PROPAGATION_MANDATORY | 使用當(dāng)前的事務(wù),如果當(dāng)前沒有事務(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)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。 |
多態(tài)解決了什么問題?
多態(tài)是指子類可以替換父類,在實際的代碼運行過程中,調(diào)用子類的方法實現(xiàn)。多態(tài)這種特性也需要編程語言提供特殊的語法機制來實現(xiàn),比如繼承、接口類。
多態(tài)可以提高代碼的擴展性和復(fù)用性,是很多設(shè)計模式、設(shè)計原則、編程技巧的代碼實現(xiàn)基礎(chǔ)。比如策略模式、基于接口而非實現(xiàn)編程、依賴倒置原則、里式替換原則、利用多態(tài)去掉冗長的 if-else 語句等等
HashMap是線程安全的嗎?
hashmap不是線程安全的,hashmap在多線程會存在下面的問題:
- JDK 1.7 HashMap 采用數(shù)組 + 鏈表的數(shù)據(jù)結(jié)構(gòu),多線程背景下,在數(shù)組擴容的時候,存在 Entry 鏈死循環(huán)和數(shù)據(jù)丟失問題。JDK 1.8 HashMap 采用數(shù)組 + 鏈表 + 紅黑二叉樹的數(shù)據(jù)結(jié)構(gòu),優(yōu)化了 1.7 中數(shù)組擴容的方案,解決了 Entry 鏈死循環(huán)和數(shù)據(jù)丟失問題。但是多線程背景下,put 方法存在數(shù)據(jù)覆蓋的問題。
如果要保證線程安全,可以通過這些方法來保證:
- 多線程環(huán)境可以使用Collections.synchronizedMap同步加鎖的方式,還可以使用HashTable,但是同步的方式顯然性能不達標,而ConurrentHashMap更適合高并發(fā)場景使用。ConcurrentHashmap在JDK1.7和1.8的版本改動比較大,1.7使用Segment+HashEntry分段鎖的方式實現(xiàn),1.8則拋棄了Segment,改為使用CAS+synchronized+Node實現(xiàn),同樣也加入了紅黑樹,避免鏈表過長導(dǎo)致性能的問題。
Java中的線程安全的集合是什么?
在 java.util 包中的線程安全的類主要 2 個,其他都是非線程安全的。
Vector:線程安全的動態(tài)數(shù)組,其內(nèi)部方法基本都經(jīng)過synchronized修飾,如果不需要線程安全,并不建議選擇,畢竟同步是有額外開銷的。Vector 內(nèi)部是使用對象數(shù)組來保存數(shù)據(jù),可以根據(jù)需要自動的增加容量,當(dāng)數(shù)組已滿時,會創(chuàng)建新的數(shù)組,并拷貝原有數(shù)組數(shù)據(jù)。
Hashtable:線程安全的哈希表,HashTable 的加鎖方法是給每個方法加上 synchronized 關(guān)鍵字,這樣鎖住的是整個 Table 對象,不支持 null 鍵和值,由于同步導(dǎo)致的性能開銷,所以已經(jīng)很少被推薦使用,如果要保證線程安全的哈希表,可以用ConcurrentHashMap。
java.util.concurrent 包提供的都是線程安全的集合:
-
- 并發(fā)Map:
ConcurrentHashMap:它與 HashTable 的主要區(qū)別是二者加鎖粒度的不同,在JDK1.7,ConcurrentHashMap加的是分段鎖,也就是Segment鎖,每個Segment 含有整個 table 的一部分,這樣不同分段之間的并發(fā)操作就互不影響。在JDK 1.8?,它取消了Segment字段,直接在table元素上加鎖,實現(xiàn)對每一行進行加鎖,進一步減小了并發(fā)沖突的概率。對于put操作,如果Key對應(yīng)的數(shù)組元素為null,則通過CAS操作(Compare and Swap)將其設(shè)置為當(dāng)前值。如果Key對應(yīng)的數(shù)組元素(也即鏈表表頭或者樹的根元素)不為null,則對該元素使用 synchronized 關(guān)鍵字申請鎖,然后進行操作。如果該 put 操作使得當(dāng)前鏈表長度超過一定閾值,則將該鏈表轉(zhuǎn)換為紅黑樹,從而提高尋址效率。
ConcurrentSkipListMap:實現(xiàn)了一個基于SkipList(跳表)算法的可排序的并發(fā)集合,SkipList是一種可以在對數(shù)預(yù)期時間內(nèi)完成搜索、插入、刪除等操作的數(shù)據(jù)結(jié)構(gòu),通過維護多個指向其他元素的“跳躍”鏈接來實現(xiàn)高效查找。
并發(fā)Set:
ConcurrentSkipListSet:是線程安全的有序的集合。底層是使用ConcurrentSkipListMap實現(xiàn)。
CopyOnWriteArraySet:是線程安全的Set實現(xiàn),它是線程安全的無序的集合,可以將它理解成線程安全的HashSet。有意思的是,CopyOnWriteArraySet和HashSet雖然都繼承于共同的父類AbstractSet;但是,HashSet是通過“散列表”實現(xiàn)的,而CopyOnWriteArraySet則是通過“動態(tài)數(shù)組(CopyOnWriteArrayList)”實現(xiàn)的,并不是散列表。
并發(fā)List:
CopyOnWriteArrayList:它是 ArrayList 的線程安全的變體,其中所有寫操作(add,set等)都通過對底層數(shù)組進行全新復(fù)制來實現(xiàn),允許存儲 null 元素。即當(dāng)對象進行寫操作時,使用了Lock鎖做同步處理,內(nèi)部拷貝了原數(shù)組,并在新數(shù)組上進行添加操作,最后將新數(shù)組替換掉舊數(shù)組;若進行的讀操作,則直接返回結(jié)果,操作過程中不需要進行同步。
并發(fā) Queue:
ConcurrentLinkedQueue:是一個適用于高并發(fā)場景下的隊列,它通過無鎖的方式(CAS),實現(xiàn)了高并發(fā)狀態(tài)下的高性能。通常,ConcurrentLinkedQueue 的性能要好于 BlockingQueue 。
BlockingQueue:與 ConcurrentLinkedQueue 的使用場景不同,BlockingQueue 的主要功能并不是在于提升高并發(fā)時的隊列性能,而在于簡化多線程間的數(shù)據(jù)共享。BlockingQueue 提供一種讀寫阻塞等待的機制,即如果消費者速度較快,則 BlockingQueue 則可能被清空,此時消費線程再試圖從 BlockingQueue 讀取數(shù)據(jù)時就會被阻塞。反之,如果生產(chǎn)線程較快,則 BlockingQueue 可能會被裝滿,此時,生產(chǎn)線程再試圖向 BlockingQueue 隊列裝入數(shù)據(jù)時,便會被阻塞等待。
并發(fā) Deque:
LinkedBlockingDeque:是一個線程安全的雙端隊列實現(xiàn)。它的內(nèi)部使用鏈表結(jié)構(gòu),每一個節(jié)點都維護了一個前驅(qū)節(jié)點和一個后驅(qū)節(jié)點。LinkedBlockingDeque 沒有進行讀寫鎖的分離,因此同一時間只能有一個線程對其進行操作
ConcurrentLinkedDeque:ConcurrentLinkedDeque是一種基于鏈接節(jié)點的無限并發(fā)鏈表??梢园踩夭l(fā)執(zhí)行插入、刪除和訪問操作。當(dāng)許多線程同時訪問一個公共集合時,ConcurrentLinkedDeque是一個合適的選擇。
ConcurrentHashMap用了悲觀鎖還是樂觀鎖?
悲觀鎖和樂觀鎖都有用到。
添加元素時首先會判斷容器是否為空:
-
-
- 如果為空則使用 ?volatile ?加
?CAS (樂觀鎖)
-
-
- ?來初始化。如果容器不為空,則根據(jù)存儲的元素計算該位置是否為空。
-
-
- 如果根據(jù)存儲的元素計算結(jié)果為空,則利用
CAS(樂觀鎖)
-
-
-
-
-
- ??設(shè)置該節(jié)點;如果根據(jù)存儲的元素計算結(jié)果不為空,則使用
synchronized(悲觀鎖)
-
-
-
- ??,然后,遍歷桶中的數(shù)據(jù),并替換或新增節(jié)點到桶中,最后再判斷是否需要轉(zhuǎn)為紅黑樹,這樣就能保證并發(fā)訪問時的線程安全了。
樂觀鎖是怎樣實現(xiàn)的?
樂觀鎖假設(shè)多個事務(wù)之間很少發(fā)生沖突,因此在讀取數(shù)據(jù)時不會加鎖,而是在更新數(shù)據(jù)時檢查數(shù)據(jù)的版本(如使用版本號或時間戳),如果版本匹配則執(zhí)行更新操作,否則認為發(fā)生了沖突。
樂觀鎖適用于讀多寫少的場景,可以減少鎖的競爭,提高并發(fā)性能。例如,數(shù)據(jù)庫中的樂觀鎖機制可以用于處理并發(fā)更新同一行數(shù)據(jù)的情況。
樂觀鎖實現(xiàn)方式可以通過 CAS 來實現(xiàn)。
CAS叫做CompareAndSwap,比較并交換,主要是通過處理器的指令來保證操作的原子性,它包含三個操作數(shù):
- 變量內(nèi)存地址,V表示舊的預(yù)期值,A表示準備設(shè)置的新值,B表示
當(dāng)執(zhí)行CAS指令時,只有當(dāng)V等于A時,才會用B去更新V的值,否則就不會執(zhí)行更新操作。
Http1.0和2.0的區(qū)別是什么?
協(xié)議版本:Http/1.0 是較早的版本,采用文本格式進行通信,雖然支持長連接,但是默認是使用短連接。從 http/1.1版本開始,默認是用了長連接,Http/2.0 是較新的版本,引入了二進制格式,以及多路復(fù)用等新特性。
性能:Http/1.0 每次請求只能響應(yīng)一個資源,多個資源需要多次請求,存在隊頭阻塞問題。Http/2.0 支持多路復(fù)用,可以在單個連接上同時傳輸多個請求和響應(yīng),提高性能。
頭部壓縮:Http/1.0 每次請求和響應(yīng)都需要攜帶完整的頭部信息,存在較大的開銷。Http/2.0 引入了頭部壓縮機制,減少了重復(fù)頭部信息的傳輸,提高了效率。
服務(wù)器推送:Http/1.0 需要等待客戶端請求后才能發(fā)送響應(yīng),無法主動推送資源。Http/2.0 支持服務(wù)器推送,服務(wù)器可以在客戶端請求之前將相關(guān)資源推送給客戶端,減少等待時間。
MySQL中的bin log的作用是什么?
binlog 是 MySQL 的 Server 層實現(xiàn)的日志,用于備份恢復(fù)、主從復(fù)制。
binlog 有 3 種格式類型,分別是 STATEMENT(默認格式)、ROW、 MIXED,區(qū)別如下:
- STATEMENT:每一條修改數(shù)據(jù)的 SQL 都會被記錄到 binlog 中(相當(dāng)于記錄了邏輯操作,所以針對這種格式, binlog 可以稱為邏輯日志),主從復(fù)制中 slave 端再根據(jù) SQL 語句重現(xiàn)。但 STATEMENT 有動態(tài)函數(shù)的問題,比如你用了 uuid 或者 now 這些函數(shù),你在主庫上執(zhí)行的結(jié)果并不是你在從庫執(zhí)行的結(jié)果,這種隨時在變的函數(shù)會導(dǎo)致復(fù)制的數(shù)據(jù)不一致;ROW:記錄行數(shù)據(jù)最終被修改成什么樣了(這種格式的日志,就不能稱為邏輯日志了),不會出現(xiàn) STATEMENT 下動態(tài)函數(shù)的問題。但 ROW 的缺點是每行數(shù)據(jù)的變化結(jié)果都會被記錄,比如執(zhí)行批量 update 語句,更新多少行數(shù)據(jù)就會產(chǎn)生多少條記錄,使 binlog 文件過大,而在 STATEMENT 格式下只會記錄一個 update 語句而已;MIXED:包含了 STATEMENT 和 ROW 模式,它會根據(jù)不同的情況自動使用 ROW 模式和 STATEMENT 模式;
算法
- 一個二叉樹,給一個target,找出大于這個樹中的節(jié)點的最大深度。