国产美女主播视频一区_国产精品蜜臀在线观看_亚洲成人动漫一区_亚洲视屏在线播放

首頁(yè) > 互聯(lián)網(wǎng)

騰訊面試體驗(yàn)倍兒好

來(lái)源:程序員魚(yú)皮 時(shí)間:2023-06-23 04:00:31

今天給大家分享騰訊春招的實(shí)習(xí)面經(jīng),崗位Java后端,主要問(wèn)了MySQL、Java、網(wǎng)絡(luò)這三大塊。


(資料圖片僅供參考)

求職者覺(jué)得這場(chǎng)面試非常有收獲,雖然都是基礎(chǔ)問(wèn)題,但是往下深挖根莖葉脈全部相連。反問(wèn)環(huán)節(jié)面試官給了他很多建議,包括面試、策略、基礎(chǔ)、算法等等,是一次寶貴的學(xué)習(xí)經(jīng)歷。

MySQL

介紹一下MySQL的索引機(jī)制

索引可以幫助我們快速搜索數(shù)據(jù),innodb 存儲(chǔ)引擎用的是 b+樹(shù)索引,葉子節(jié)點(diǎn)存放的是索引+數(shù)據(jù),非葉子節(jié)點(diǎn)只存放索引。

可以按照四個(gè)角度來(lái)分類(lèi)索引。

按「數(shù)據(jù)結(jié)構(gòu)」分類(lèi): B+tree索引、Hash索引、Full-text索引
按「物理存儲(chǔ)」分類(lèi): 聚簇索引(主鍵索引)、二級(jí)索引(輔助索引)
按「字段特性」分類(lèi): 主鍵索引、唯一索引、普通索引、前綴索引
按「字段個(gè)數(shù)」分類(lèi): 單列索引、聯(lián)合索引

聯(lián)合索引是什么?

通過(guò)將多個(gè)字段組合成一個(gè)索引,該索引就被稱(chēng)為聯(lián)合索引。

比如,將商品表中的 product_no 和 name 字段組合成聯(lián)合索引(product_no, name),創(chuàng)建聯(lián)合索引的方式如下:

CREATEINDEXindex_product_no_nameONproduct(product_no,name);

聯(lián)合索引(product_no, name)的 B+Tree 示意圖如下(圖中葉子節(jié)點(diǎn)之間畫(huà)了單向鏈表,但是實(shí)際上是雙向鏈表,原圖找不到了,修改不了,偷個(gè)懶不重畫(huà)了,大家腦補(bǔ)成雙向鏈表就行)。

聯(lián)合索引

可以看到,聯(lián)合索引的非葉子節(jié)點(diǎn)用兩個(gè)字段的值作為 B+Tree 的 key 值。當(dāng)在聯(lián)合索引查詢(xún)數(shù)據(jù)時(shí),先按 product_no 字段比較,在 product_no 相同的情況下再按 name 字段比較。

也就是說(shuō),聯(lián)合索引查詢(xún)的 B+Tree 是先按 product_no 進(jìn)行排序,然后再 product_no 相同的情況再按 name 字段排序。

因此,使用聯(lián)合索引時(shí),存在最左匹配原則,也就是按照最左優(yōu)先的方式進(jìn)行索引的匹配。在使用聯(lián)合索引進(jìn)行查詢(xún)的時(shí)候,如果不遵循「最左匹配原則」,聯(lián)合索引會(huì)失效,這樣就無(wú)法利用到索引快速查詢(xún)的特性了。

什么是聚簇索引?

聚簇索引的 B+Tree 的葉子節(jié)點(diǎn)存放的是實(shí)際數(shù)據(jù),所有完整的用戶(hù)記錄都存放在主鍵索引的 B+Tree 的葉子節(jié)點(diǎn)里。

什么是覆蓋索引?

在查詢(xún)時(shí)使用了二級(jí)索引,如果查詢(xún)的數(shù)據(jù)能在二級(jí)索引里查詢(xún)的到,那么就不需要回表,這個(gè)過(guò)程就是覆蓋索引。如果查詢(xún)的數(shù)據(jù)不在二級(jí)索引里,就會(huì)先檢索二級(jí)索引,找到對(duì)應(yīng)的葉子節(jié)點(diǎn),獲取到主鍵值后,然后再檢索主鍵索引,就能查詢(xún)到數(shù)據(jù)了,這個(gè)過(guò)程就是回表。

整個(gè)索引查詢(xún)的過(guò)程是怎樣的?

InnoDB 里的 B+ 樹(shù)中的每個(gè)節(jié)點(diǎn)都是一個(gè)數(shù)據(jù)頁(yè),結(jié)構(gòu)示意圖如下:

B+ 樹(shù)如何實(shí)現(xiàn)快速查找主鍵為 6 的記錄,以上圖為例子:

從根節(jié)點(diǎn)開(kāi)始,通過(guò)二分法快速定位到符合頁(yè)內(nèi)范圍包含查詢(xún)值的頁(yè),因?yàn)椴樵?xún)的主鍵值為 6,在[1, 7)范圍之間,所以到頁(yè) 30 中查找更詳細(xì)的目錄項(xiàng);
在非葉子節(jié)點(diǎn)(頁(yè)30)中,繼續(xù)通過(guò)二分法快速定位到符合頁(yè)內(nèi)范圍包含查詢(xún)值的頁(yè),主鍵值大于 5,所以就到葉子節(jié)點(diǎn)(頁(yè)16)查找記錄;
接著,在葉子節(jié)點(diǎn)(頁(yè)16)中,通過(guò)槽查找記錄時(shí),使用二分法快速定位要查詢(xún)的記錄在哪個(gè)槽(哪個(gè)記錄分組),定位到槽后,再遍歷槽內(nèi)的所有記錄,找到主鍵為 6 的記錄。

可以看到,在定位記錄所在哪一個(gè)頁(yè)時(shí),也是通過(guò)二分法快速定位到包含該記錄的頁(yè)。定位到該頁(yè)后,又會(huì)在該頁(yè)內(nèi)進(jìn)行二分法快速定位記錄所在的分組(槽號(hào)),最后在分組內(nèi)進(jìn)行遍歷查找。

事務(wù)的隔離級(jí)別有哪些?

讀未提交,指一個(gè)事務(wù)還沒(méi)提交時(shí),它做的變更就能被其他事務(wù)看到;
讀提交,指一個(gè)事務(wù)提交之后,它做的變更才能被其他事務(wù)看到;
可重復(fù)讀,指一個(gè)事務(wù)執(zhí)行過(guò)程中看到的數(shù)據(jù),一直跟這個(gè)事務(wù)啟動(dòng)時(shí)看到的數(shù)據(jù)是一致的, MySQL InnoDB 引擎的默認(rèn)隔離級(jí)別
串行化;會(huì)對(duì)記錄加上讀寫(xiě)鎖,在多個(gè)事務(wù)對(duì)這條記錄進(jìn)行讀寫(xiě)操作時(shí),如果發(fā)生了讀寫(xiě)沖突的時(shí)候,后訪問(wèn)的事務(wù)必須等前一個(gè)事務(wù)執(zhí)行完成,才能繼續(xù)執(zhí)行;

臟讀、幻讀、不可重讀分別是什么意思?

臟讀:如果一個(gè)事務(wù)「讀到」了另一個(gè)「未提交事務(wù)修改過(guò)的數(shù)據(jù)」,就意味著發(fā)生了「臟讀」現(xiàn)象。
幻讀:在一個(gè)事務(wù)內(nèi)多次查詢(xún)某個(gè)符合查詢(xún)條件的「記錄數(shù)量」,如果出現(xiàn)前后兩次查詢(xún)到的記錄數(shù)量不一樣的情況,就意味著發(fā)生了「幻讀」現(xiàn)象。
不可重復(fù)讀:在一個(gè)事務(wù)內(nèi)多次讀取同一個(gè)數(shù)據(jù),如果出現(xiàn)前后兩次讀到的數(shù)據(jù)不一樣的情況,就意味著發(fā)生了「不可重復(fù)讀」現(xiàn)象。

InnoDB 多版本并發(fā)控制的具體原理,底層細(xì)節(jié)?

對(duì)于「讀提交」和「可重復(fù)讀」隔離級(jí)別的事務(wù)來(lái)說(shuō),它們是通過(guò) Read View 來(lái)實(shí)現(xiàn)的,它們的區(qū)別在于創(chuàng)建 Read View 的時(shí)機(jī)不同,大家可以把 Read View 理解成一個(gè)數(shù)據(jù)快照,就像相機(jī)拍照那樣,定格某一時(shí)刻的風(fēng)景。

「讀提交」隔離級(jí)別是在「每個(gè)select語(yǔ)句執(zhí)行前」都會(huì)重新生成一個(gè) Read View;
「可重復(fù)讀」隔離級(jí)別是執(zhí)行第一條select時(shí),生成一個(gè) Read View,然后整個(gè)事務(wù)期間都在用這個(gè) Read View。

Read View 有四個(gè)重要的字段:

m_ids :指的是在創(chuàng)建 Read View 時(shí),當(dāng)前數(shù)據(jù)庫(kù)中「活躍事務(wù)」的 事務(wù) id 列表,注意是一個(gè)列表, “活躍事務(wù)”指的就是,啟動(dòng)了但還沒(méi)提交的事務(wù)
min_trx_id :指的是在創(chuàng)建 Read View 時(shí),當(dāng)前數(shù)據(jù)庫(kù)中「活躍事務(wù)」中事務(wù) id 最小的事務(wù),也就是 m_ids 的最小值。
max_trx_id :這個(gè)并不是 m_ids 的最大值,而是 創(chuàng)建 Read View 時(shí)當(dāng)前數(shù)據(jù)庫(kù)中應(yīng)該給下一個(gè)事務(wù)的 id 值,也就是全局事務(wù)中最大的事務(wù) id 值 + 1;
creator_trx_id :指的是 創(chuàng)建該 Read View 的事務(wù)的事務(wù) id

對(duì)于使用 InnoDB 存儲(chǔ)引擎的數(shù)據(jù)庫(kù)表,它的聚簇索引記錄中都包含下面兩個(gè)隱藏列:

trx_id,當(dāng)一個(gè)事務(wù)對(duì)某條聚簇索引記錄進(jìn)行改動(dòng)時(shí),就會(huì) 把該事務(wù)的事務(wù) id 記錄在 trx_id 隱藏列里
roll_pointer,每次對(duì)某條聚簇索引記錄進(jìn)行改動(dòng)時(shí),都會(huì)把舊版本的記錄寫(xiě)入到 undo 日志中,然后 這個(gè)隱藏列是個(gè)指針,指向每一個(gè)舊版本記錄,于是就可以通過(guò)它找到修改前的記錄。

在創(chuàng)建 Read View 后,我們可以將記錄中的 trx_id 劃分這三種情況:

一個(gè)事務(wù)去訪問(wèn)記錄的時(shí)候,除了自己的更新記錄總是可見(jiàn)之外,還有這幾種情況:

如果記錄的 trx_id 值小于 Read View 中的 min_trx_id值,表示這個(gè)版本的記錄是在創(chuàng)建 Read View 已經(jīng)提交的事務(wù)生成的,所以該版本的記錄對(duì)當(dāng)前事務(wù) 可見(jiàn)
如果記錄的 trx_id 值大于等于 Read View 中的 max_trx_id值,表示這個(gè)版本的記錄是在創(chuàng)建 Read View 才啟動(dòng)的事務(wù)生成的,所以該版本的記錄對(duì)當(dāng)前事務(wù) 不可見(jiàn)
如果記錄的 trx_id 值在 Read View 的 min_trx_id 和 max_trx_id 之間,需要判斷 trx_id 是否在 m_ids 列表中:
如果記錄的 trx_id m_ids列表中,表示生成該版本記錄的活躍事務(wù)依然活躍著(還沒(méi)提交事務(wù)),所以該版本的記錄對(duì)當(dāng)前事務(wù) 不可見(jiàn)
如果記錄的 trx_id 不在m_ids列表中,表示生成該版本記錄的活躍事務(wù)已經(jīng)被提交,所以該版本的記錄對(duì)當(dāng)前事務(wù) 可見(jiàn)

這種通過(guò)「版本鏈」來(lái)控制并發(fā)事務(wù)訪問(wèn)同一個(gè)記錄時(shí)的行為就叫 MVCC(多版本并發(fā)控制)。

next Key是什么,怎么實(shí)現(xiàn)?

Next-Key Lock 稱(chēng)為臨鍵鎖,是 Record Lock + Gap Lock 的組合,鎖定一個(gè)范圍,并且鎖定記錄本身。

假設(shè),表中有一個(gè)范圍 id 為(3,5] 的 next-key lock,那么其他事務(wù)即不能插入 id = 4 記錄,也不能修改 id = 5 這條記錄。

所以,next-key lock 即能保護(hù)該記錄,又能阻止其他事務(wù)將新紀(jì)錄插入到被保護(hù)記錄前面的間隙中。

索引失效的場(chǎng)景有哪些,你知道什么改進(jìn)方法嗎?

當(dāng)我們使用左或者左右模糊匹配的時(shí)候,也就是 like %xx或者 like %xx%這兩種方式都會(huì)造成索引失效;
當(dāng)我們?cè)诓樵?xún)條件中對(duì)索引列使用函數(shù),就會(huì)導(dǎo)致索引失效。
當(dāng)我們?cè)诓樵?xún)條件中對(duì)索引列進(jìn)行表達(dá)式計(jì)算,也是無(wú)法走索引的。
MySQL 在遇到字符串和數(shù)字比較的時(shí)候,會(huì)自動(dòng)把字符串轉(zhuǎn)為數(shù)字,然后再進(jìn)行比較。如果字符串是索引列,而條件語(yǔ)句中的輸入?yún)?shù)是數(shù)字的話(huà),那么索引列會(huì)發(fā)生隱式類(lèi)型轉(zhuǎn)換,由于隱式類(lèi)型轉(zhuǎn)換是通過(guò) CAST 函數(shù)實(shí)現(xiàn)的,等同于對(duì)索引列使用了函數(shù),所以就會(huì)導(dǎo)致索引失效。
聯(lián)合索引要能正確使用需要遵循最左匹配原則,也就是按照最左優(yōu)先的方式進(jìn)行索引的匹配,否則就會(huì)導(dǎo)致索引失效。
在 WHERE 子句中,如果在 OR 前的條件列是索引列,而在 OR 后的條件列不是索引列,那么索引會(huì)失效。

提交事務(wù)的一整個(gè)過(guò)程,每個(gè)日志都是怎么工作的?

具體更新一條記錄 UPDATE t_user SET name = "xiaolin" WHERE id = 1;的流程如下:

執(zhí)行器負(fù)責(zé)具體執(zhí)行,會(huì)調(diào)用存儲(chǔ)引擎的接口,通過(guò)主鍵索引樹(shù)搜索獲取 id = 1 這一行記錄:
如果 id=1 這一行所在的數(shù)據(jù)頁(yè)本來(lái)就在 buffer pool 中,就直接返回給執(zhí)行器更新;
如果記錄不在 buffer pool,將數(shù)據(jù)頁(yè)從磁盤(pán)讀入到 buffer pool,返回記錄給執(zhí)行器。
執(zhí)行器得到聚簇索引記錄后,會(huì)看一下更新前的記錄和更新后的記錄是否一樣:
如果一樣的話(huà)就不進(jìn)行后續(xù)更新流程;
如果不一樣的話(huà)就把更新前的記錄和更新后的記錄都當(dāng)作參數(shù)傳給 InnoDB 層,讓 InnoDB 真正的執(zhí)行更新記錄的操作;
開(kāi)啟事務(wù), InnoDB 層更新記錄前,首先要記錄相應(yīng)的 undo log,因?yàn)檫@是更新操作,需要把被更新的列的舊值記下來(lái),也就是要生成一條 undo log,undo log 會(huì)寫(xiě)入 Buffer Pool 中的 Undo 頁(yè)面,不過(guò)在內(nèi)存修改該 Undo 頁(yè)面后,需要記錄對(duì)應(yīng)的 redo log。
InnoDB 層開(kāi)始更新記錄,會(huì)先更新內(nèi)存(同時(shí)標(biāo)記為臟頁(yè)),然后將記錄寫(xiě)到 redo log 里面,這個(gè)時(shí)候更新就算完成了。為了減少磁盤(pán)I/O,不會(huì)立即將臟頁(yè)寫(xiě)入磁盤(pán),后續(xù)由后臺(tái)線(xiàn)程選擇一個(gè)合適的時(shí)機(jī)將臟頁(yè)寫(xiě)入到磁盤(pán)。這就是 WAL 技術(shù),MySQL 的寫(xiě)操作并不是立刻寫(xiě)到磁盤(pán)上,而是先寫(xiě) redo 日志,然后在合適的時(shí)間再將修改的行數(shù)據(jù)寫(xiě)到磁盤(pán)上。
至此,一條記錄更新完了。
在一條更新語(yǔ)句執(zhí)行完成后,然后開(kāi)始記錄該語(yǔ)句對(duì)應(yīng)的 binlog,此時(shí)記錄的 binlog 會(huì)被保存到 binlog cache,并沒(méi)有刷新到硬盤(pán)上的 binlog 文件,在事務(wù)提交時(shí)才會(huì)統(tǒng)一將該事務(wù)運(yùn)行過(guò)程中的所有 binlog 刷新到硬盤(pán)。
事務(wù)提交(為了方便說(shuō)明,這里不說(shuō)組提交的過(guò)程,只說(shuō)兩階段提交):
prepare 階段:將 redo log 對(duì)應(yīng)的事務(wù)狀態(tài)設(shè)置為 prepare,然后將 redo log 刷新到硬盤(pán);
commit 階段:將 binlog 刷新到磁盤(pán),接著調(diào)用引擎的提交事務(wù)接口,將 redo log 狀態(tài)設(shè)置為 commit(將事務(wù)設(shè)置為 commit 狀態(tài)后,刷入到磁盤(pán) redo log 文件);
至此,一條更新語(yǔ)句執(zhí)行完成。

Java

JVM內(nèi)存區(qū)域 每一個(gè)區(qū)域的內(nèi)容?

JVM的內(nèi)存結(jié)構(gòu)主要分為以下幾個(gè)部分:

程序計(jì)數(shù)器(Program Counter Register):每個(gè)線(xiàn)程都有一個(gè)程序計(jì)數(shù)器。當(dāng)線(xiàn)程執(zhí)行 Java 方法時(shí),程序計(jì)數(shù)器保存當(dāng)前執(zhí)行指令的地址,以便在 JVM 調(diào)用其他方法或恢復(fù)線(xiàn)程執(zhí)行時(shí)重新回到正確的位置。

Java 虛擬機(jī)棧(Java Virtual Machine Stacks):每個(gè)線(xiàn)程都有一個(gè)虛擬機(jī)棧。虛擬機(jī)棧保存著方法執(zhí)行期間的局部變量、操作數(shù)棧、方法出口等信息。線(xiàn)程每調(diào)用一個(gè) Java 方法時(shí),會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame),棧幀包含著該方法的局部變量、操作數(shù)棧、方法返回地址等信息。棧幀在方法執(zhí)行結(jié)束后會(huì)被彈出。

本地方法棧(Native Method Stack):與 Java 虛擬機(jī)棧類(lèi)似,但是為本地方法服務(wù)。

Java 堆(Java Heap):Java 堆是 Java 虛擬機(jī)中最大的一塊內(nèi)存區(qū)域,用于存儲(chǔ)各種類(lèi)型的對(duì)象實(shí)例,也是垃圾收集器的主要工作區(qū)域。Java 堆是所有線(xiàn)程共享的部分。

方法區(qū)(Method Area):方法區(qū)也是所有線(xiàn)程共享的部分,它用于存儲(chǔ)類(lèi)的加載信息、靜態(tài)變量、常量池、方法字節(jié)碼等數(shù)據(jù)。在 Java 8 及以前的版本中,方法區(qū)被實(shí)現(xiàn)為永久代(Permanent Generation),在 Java 8 中被改為元空間(Metaspace)。

JVM異常問(wèn)題?

StackOverflowError(線(xiàn)程請(qǐng)求棧深度超過(guò)虛擬機(jī)所允許的最大深度)
OutOfMemoryError(堆內(nèi)存不夠用)
PermGen space(方法區(qū)內(nèi)存不夠用)。

String保存在哪里呢

String 保存在字符串常量池中,不同于其他對(duì)象,它的值是不可變的,且可以被多個(gè)引用共享。

java版本改動(dòng)問(wèn)題 有哪些主要區(qū)別?

Java 7 新特性:鉆石操作符、try-with-resource語(yǔ)句、支持動(dòng)態(tài)類(lèi)型語(yǔ)言、Fork/Join框架等。

Java 8 新特性:Lambda 表達(dá)式、Stream API、新的 Date/Time API、Nashorn JavaScript 引擎等。

怎么找到需要回收的垃圾?

Java中的垃圾回收機(jī)制通過(guò)判斷對(duì)象是否可達(dá)來(lái)確定哪些對(duì)象可以被回收。當(dāng)一個(gè)對(duì)象沒(méi)有任何引用指向它時(shí),它就可以被回收,這個(gè)過(guò)程由JVM的垃圾回收器自動(dòng)完成。

JVM使用可達(dá)性分析算法來(lái)判斷對(duì)象是否可達(dá)。從GC Roots對(duì)象開(kāi)始,通過(guò)一系列的引用鏈來(lái)遍歷所有的對(duì)象,如果一個(gè)對(duì)象不可達(dá),則說(shuō)明它已經(jīng)死亡,可以被回收了。

在Java中,有4種引用類(lèi)型:強(qiáng)引用、軟引用、弱引用和虛引用。其中,強(qiáng)引用是最常見(jiàn)的引用類(lèi)型,只要強(qiáng)引用存在,垃圾回收器就不會(huì)回收該對(duì)象。軟引用、弱引用和虛引用則分別表示對(duì)對(duì)象的軟引用、弱引用和虛引用,當(dāng)垃圾回收器進(jìn)行垃圾回收時(shí),會(huì)根據(jù)不同的引用類(lèi)型來(lái)決定是否回收對(duì)象。

有哪些常見(jiàn)的垃圾回收器,舉幾個(gè)說(shuō)說(shuō)?

Serial收集器:?jiǎn)尉€(xiàn)程的垃圾回收器,使用標(biāo)記-復(fù)制算法,適合小型應(yīng)用程序或客戶(hù)端應(yīng)用程序。

Parallel收集器:多線(xiàn)程的垃圾回收器,使用標(biāo)記-復(fù)制算法,適合在后臺(tái)運(yùn)行的中型應(yīng)用程序。

CMS收集器:并發(fā)垃圾回收器,使用標(biāo)記-清除算法,適合對(duì)響應(yīng)時(shí)間有要求的中型應(yīng)用程序。

G1收集器:并發(fā)垃圾回收器,使用標(biāo)記-整理算法,適合對(duì)響應(yīng)時(shí)間有要求且堆內(nèi)存較大的應(yīng)用程序。

其中,Serial收集器和Parallel收集器是新生代收集器,CMS和G1是老年代收集器。

HashMap底層怎么實(shí)現(xiàn)的 ?線(xiàn)程安全嗎?

HashMap底層是基于數(shù)組和鏈表實(shí)現(xiàn)的。簡(jiǎn)單來(lái)說(shuō),HashMap將key通過(guò)hash算法映射到數(shù)組中,然后在對(duì)應(yīng)的鏈表中查找value。當(dāng)多個(gè)key的hash值相同時(shí),會(huì)在同一個(gè)數(shù)組位置上使用鏈表來(lái)存儲(chǔ)這些key-value。但是,當(dāng)鏈表長(zhǎng)度太長(zhǎng)時(shí),會(huì)影響HashMap的性能,因此在中,當(dāng)鏈表長(zhǎng)度超過(guò)閾值時(shí),會(huì)將鏈表轉(zhuǎn)換為紅黑樹(shù),以提高查找效率。

HashMap不是線(xiàn)程安全的,因?yàn)槎鄠€(gè)線(xiàn)程同時(shí)訪問(wèn)HashMap時(shí)可能會(huì)導(dǎo)致數(shù)據(jù)不一致的問(wèn)題。可以使用ConcurrentHashMap來(lái)實(shí)現(xiàn)線(xiàn)程安全的Map。

紅黑樹(shù)是什么?

紅黑樹(shù)是一種自平衡的二叉查找樹(shù),可以保證在最壞情況下基本動(dòng)態(tài)操作的時(shí)間復(fù)雜度為O(log n)。紅黑樹(shù)中的每個(gè)節(jié)點(diǎn)都有一個(gè)顏色屬性,可以是紅色或黑色。紅黑樹(shù)滿(mǎn)足以下5個(gè)性質(zhì):

每個(gè)節(jié)點(diǎn)要么是紅色,要么是黑色。
根節(jié)點(diǎn)是黑色的。
每個(gè)葉子節(jié)點(diǎn)(NIL節(jié)點(diǎn),空節(jié)點(diǎn))是黑色的。
如果一個(gè)節(jié)點(diǎn)是紅色的,則它的兩個(gè)子節(jié)點(diǎn)都是黑色的。
對(duì)于每個(gè)節(jié)點(diǎn),從該節(jié)點(diǎn)到其所有后代葉子節(jié)點(diǎn)的簡(jiǎn)單路徑上,均包含相同數(shù)目的黑色節(jié)點(diǎn)。

通過(guò)這些性質(zhì),紅黑樹(shù)可以保證在插入和刪除節(jié)點(diǎn)時(shí),自動(dòng)調(diào)整樹(shù)的結(jié)構(gòu),以保持樹(shù)的平衡和性質(zhì)的滿(mǎn)足。相比于普通的二叉查找樹(shù),紅黑樹(shù)的平衡性更好,查找、插入和刪除都具有更穩(wěn)定的時(shí)間復(fù)雜度,因此在很多場(chǎng)景下被廣泛應(yīng)用。

什么是公平鎖和非公平鎖?

公平鎖和非公平鎖是針對(duì)鎖的獲取方式而言的。

公平鎖是指多個(gè)線(xiàn)程按照申請(qǐng)鎖的順序來(lái)獲取鎖,即先到先得的原則。當(dāng)線(xiàn)程A釋放鎖后,線(xiàn)程B、C、D依次獲取鎖,如果此時(shí)線(xiàn)程E申請(qǐng)鎖,則它需要等待B、C、D依次獲取到鎖并釋放鎖后才能獲取鎖。

非公平鎖是指多個(gè)線(xiàn)程獲取鎖的順序是隨機(jī)的,不保證公平性。當(dāng)線(xiàn)程A釋放鎖后,線(xiàn)程B、C、D等線(xiàn)程都可以通過(guò)競(jìng)爭(zhēng)獲取到鎖,而此時(shí)線(xiàn)程E也可以通過(guò)競(jìng)爭(zhēng)獲取到鎖。

在實(shí)際應(yīng)用中,公平鎖可以避免饑餓現(xiàn)象,但是由于需要維護(hù)線(xiàn)程隊(duì)列,因此效率相對(duì)較低。而非公平鎖由于不需要維護(hù)線(xiàn)程隊(duì)列,因此效率相對(duì)較高,但是可能會(huì)導(dǎo)致某些線(xiàn)程長(zhǎng)時(shí)間無(wú)法獲取鎖。

ThreadLocal 是什么?

ThreadLocal是Java中的一個(gè)線(xiàn)程封閉技術(shù),它可以讓每個(gè)線(xiàn)程都擁有自己?jiǎn)为?dú)的變量副本,從而保證線(xiàn)程安全。ThreadLocal提供了一種線(xiàn)程本地存儲(chǔ)的機(jī)制,為每個(gè)線(xiàn)程提供一個(gè)獨(dú)立的變量副本,使得每個(gè)線(xiàn)程中的變量互不干擾。

計(jì)算機(jī)網(wǎng)絡(luò)

TCP 三次握手、四次揮手的過(guò)程?

三次握手的過(guò)程:

TCP 三次握手
一開(kāi)始,客戶(hù)端和服務(wù)端都處于 CLOSE狀態(tài)。先是服務(wù)端主動(dòng)監(jiān)聽(tīng)某個(gè)端口,處于 LISTEN狀態(tài)
客戶(hù)端會(huì)隨機(jī)初始化序號(hào)( client_isn),將此序號(hào)置于 TCP 首部的「序號(hào)」字段中,同時(shí)把 SYN標(biāo)志位置為 1,表示 SYN報(bào)文。接著把第一個(gè) SYN 報(bào)文發(fā)送給服務(wù)端,表示向服務(wù)端發(fā)起連接,該報(bào)文不包含應(yīng)用層數(shù)據(jù),之后客戶(hù)端處于 SYN-SENT狀態(tài)。
服務(wù)端收到客戶(hù)端的 SYN報(bào)文后,首先服務(wù)端也隨機(jī)初始化自己的序號(hào)( server_isn),將此序號(hào)填入 TCP 首部的「序號(hào)」字段中,其次把 TCP 首部的「確認(rèn)應(yīng)答號(hào)」字段填入 client_isn + 1, 接著把 SYNACK標(biāo)志位置為 1。最后把該報(bào)文發(fā)給客戶(hù)端,該報(bào)文也不包含應(yīng)用層數(shù)據(jù),之后服務(wù)端處于 SYN-RCVD狀態(tài)。
客戶(hù)端收到服務(wù)端報(bào)文后,還要向服務(wù)端回應(yīng)最后一個(gè)應(yīng)答報(bào)文,首先該應(yīng)答報(bào)文 TCP 首部 ACK標(biāo)志位置為 1,其次「確認(rèn)應(yīng)答號(hào)」字段填入 server_isn + 1,最后把報(bào)文發(fā)送給服務(wù)端,這次報(bào)文可以攜帶客戶(hù)到服務(wù)端的數(shù)據(jù),之后客戶(hù)端處于 ESTABLISHED狀態(tài)。
服務(wù)端收到客戶(hù)端的應(yīng)答報(bào)文后,也進(jìn)入 ESTABLISHED狀態(tài)。

四次揮手的過(guò)程:

客戶(hù)端打算關(guān)閉連接,此時(shí)會(huì)發(fā)送一個(gè) TCP 首部 FIN標(biāo)志位被置為 1的報(bào)文,也即 FIN報(bào)文,之后客戶(hù)端進(jìn)入 FIN_WAIT_1狀態(tài)。
服務(wù)端收到該報(bào)文后,就向客戶(hù)端發(fā)送 ACK應(yīng)答報(bào)文,接著服務(wù)端進(jìn)入 CLOSE_WAIT狀態(tài)。
客戶(hù)端收到服務(wù)端的 ACK應(yīng)答報(bào)文后,之后進(jìn)入 FIN_WAIT_2狀態(tài)。
等待服務(wù)端處理完數(shù)據(jù)后,也向客戶(hù)端發(fā)送 FIN報(bào)文,之后服務(wù)端進(jìn)入 LAST_ACK狀態(tài)。
客戶(hù)端收到服務(wù)端的 FIN報(bào)文后,回一個(gè) ACK應(yīng)答報(bào)文,之后進(jìn)入 TIME_WAIT狀態(tài)
服務(wù)端收到了 ACK應(yīng)答報(bào)文后,就進(jìn)入了 CLOSE狀態(tài),至此服務(wù)端已經(jīng)完成連接的關(guān)閉。
客戶(hù)端在經(jīng)過(guò) 2MSL一段時(shí)間后,自動(dòng)進(jìn)入 CLOSE狀態(tài),至此客戶(hù)端也完成連接的關(guān)閉。

為什么要三次握手、四次揮手?

三次握手的原因:

三次握手可以阻止重復(fù)歷史連接的初始化
三次握手可以同步雙方的初始序列號(hào)
三次握手可以避免資源浪費(fèi)

四次次揮手的原因:

服務(wù)端通常需要等待完成數(shù)據(jù)的發(fā)送和處理,所以服務(wù)端的 ACK 和 FIN 一般都會(huì)分開(kāi)發(fā)送,因此是需要四次揮手。

LINUX有哪些IO機(jī)制?

阻塞IO(Blocking IO):應(yīng)用程序在進(jìn)行IO操作時(shí),會(huì)一直阻塞等待IO完成,期間無(wú)法進(jìn)行其他操作。

非阻塞IO(Non-blocking IO):應(yīng)用程序在進(jìn)行IO操作時(shí),會(huì)立即返回,無(wú)論IO操作是否完成,應(yīng)用程序都可以進(jìn)行其他操作。需要通過(guò)輪詢(xún)的方式來(lái)判斷IO是否完成,因此效率較低。

IO多路復(fù)用(IO Multiplexing):通過(guò)select、poll、epoll等系統(tǒng)調(diào)用,在一個(gè)進(jìn)程中可以同時(shí)監(jiān)控多個(gè)文件描述符,當(dāng)有任何一個(gè)文件描述符就緒時(shí),就可以進(jìn)行IO操作。

信號(hào)驅(qū)動(dòng)IO(Signal Driven IO):應(yīng)用程序在進(jìn)行IO操作時(shí),向內(nèi)核注冊(cè)一個(gè)信號(hào)處理函數(shù),內(nèi)核在IO完成時(shí)會(huì)向應(yīng)用程序發(fā)送一個(gè)信號(hào),應(yīng)用程序收到信號(hào)后再進(jìn)行數(shù)據(jù)處理。

異步IO(Asynchronous IO):應(yīng)用程序進(jìn)行IO操作時(shí),可以立即返回,內(nèi)核負(fù)責(zé)將數(shù)據(jù)讀取到指定的緩沖區(qū)中,并在完成后通知應(yīng)用程序,應(yīng)用程序可以繼續(xù)進(jìn)行其他操作。異步IO需要操作系統(tǒng)和硬件的支持,目前主要應(yīng)用于高性能IO場(chǎng)景。

select poll epoll,底層實(shí)現(xiàn)有什么區(qū)別?

select 和 poll 并沒(méi)有本質(zhì)區(qū)別,它們內(nèi)部都是使用「線(xiàn)性結(jié)構(gòu)」來(lái)存儲(chǔ)進(jìn)程關(guān)注的 Socket 集合。

在使用的時(shí)候,首先需要把關(guān)注的 Socket 集合通過(guò) select/poll 系統(tǒng)調(diào)用從用戶(hù)態(tài)拷貝到內(nèi)核態(tài),然后由內(nèi)核檢測(cè)事件,當(dāng)有網(wǎng)絡(luò)事件產(chǎn)生時(shí),內(nèi)核需要遍歷進(jìn)程關(guān)注 Socket 集合,找到對(duì)應(yīng)的 Socket,并設(shè)置其狀態(tài)為可讀/可寫(xiě),然后把整個(gè) Socket 集合從內(nèi)核態(tài)拷貝到用戶(hù)態(tài),用戶(hù)態(tài)還要繼續(xù)遍歷整個(gè) Socket 集合找到可讀/可寫(xiě)的 Socket,然后對(duì)其處理。

很明顯發(fā)現(xiàn),select 和 poll 的缺陷在于,當(dāng)客戶(hù)端越多,也就是 Socket 集合越大,Socket 集合的遍歷和拷貝會(huì)帶來(lái)很大的開(kāi)銷(xiāo),因此也很難應(yīng)對(duì) C10K。

epoll 是解決 C10K 問(wèn)題的利器,通過(guò)兩個(gè)方面解決了 select/poll 的問(wèn)題。

epoll 在內(nèi)核里使用「紅黑樹(shù)」來(lái)關(guān)注進(jìn)程所有待檢測(cè)的 Socket,紅黑樹(shù)是個(gè)高效的數(shù)據(jù)結(jié)構(gòu),增刪改一般時(shí)間復(fù)雜度是 O(logn),通過(guò)對(duì)這棵黑紅樹(shù)的管理,不需要像 select/poll 在每次操作時(shí)都傳入整個(gè) Socket 集合,減少了內(nèi)核和用戶(hù)空間大量的數(shù)據(jù)拷貝和內(nèi)存分配。
epoll 使用事件驅(qū)動(dòng)的機(jī)制,內(nèi)核里維護(hù)了一個(gè)「鏈表」來(lái)記錄就緒事件,只將有事件發(fā)生的 Socket 集合傳遞給應(yīng)用程序,不需要像 select/poll 那樣輪詢(xún)掃描整個(gè)集合(包含有和無(wú)事件的 Socket ),大大提高了檢測(cè)的效率。

BIO 和 NIO 的區(qū)別?

Java中,BIO和NIO都是IO模型,它們的主要區(qū)別在于:

阻塞和非阻塞:BIO采用阻塞模式,即在進(jìn)行IO操作時(shí),線(xiàn)程會(huì)一直阻塞等待IO完成。而NIO采用非阻塞模式,即在進(jìn)行IO操作時(shí),線(xiàn)程會(huì)立即返回,無(wú)論IO操作是否完成,線(xiàn)程都可以進(jìn)行其他操作。
IO模型:BIO采用同步阻塞IO模型,即一個(gè)線(xiàn)程只能處理一個(gè)連接,當(dāng)有大量連接時(shí),需要大量的線(xiàn)程來(lái)處理,會(huì)導(dǎo)致系統(tǒng)資源浪費(fèi)。NIO采用同步非阻塞IO模型,將客戶(hù)端發(fā)送的連接請(qǐng)求都會(huì)注冊(cè)到多路復(fù)用器上,這樣一個(gè)線(xiàn)程可以處理多個(gè)連接,當(dāng)有大量連接時(shí),只需要少量的線(xiàn)程來(lái)處理,可以有效地提高系統(tǒng)資源利用率。

算法

鏈表判斷相交

publicListNodegetIntersectionNode(ListNodeheadA,ListNodeheadB){if(headA==null||headB==null)returnnull;ListNodepA=headA,pB=headB;while(pA!=pB){pA=pA==null?headB:;pB=pB==null?headA:;}returnpA;}

面試總結(jié)

求職者的感覺(jué)

非常有收獲的一次面試,值得之后自己?jiǎn)为?dú)寫(xiě)一寫(xiě)文章去記錄一下。基礎(chǔ)不牢地動(dòng)山搖,雖然都是基礎(chǔ)問(wèn)題,但是往下深挖根莖葉脈全部相連,這些問(wèn)題面試題里面都有解,但是自己真的是只知道表面,淺淺看個(gè)大概就上戰(zhàn)場(chǎng)了,還有就是非常感謝面試官,反問(wèn)環(huán)節(jié)給了我很多建議,包括面試、策略、基礎(chǔ)、算法等等,是一次寶貴的學(xué)習(xí)經(jīng)歷,說(shuō)不遺憾是假的,但我很開(kāi)心,有所收獲就好。

求職者的不足之處

基礎(chǔ)不夠扎實(shí),很多只知其表不知其里,而且面試官經(jīng)驗(yàn)豐富,非常敏銳,當(dāng)時(shí)壓力也很大,被問(wèn)倒了心態(tài)也不穩(wěn),有的可以答出來(lái)的也沒(méi)想起來(lái)怎么說(shuō)。

沒(méi)有幾個(gè)答的特別好的,稍微說(shuō)一點(diǎn)就會(huì)被問(wèn)深直到不會(huì),這里就不貼當(dāng)時(shí)回答了,說(shuō)的都很淺,下來(lái)每一個(gè)問(wèn)題都要仔細(xì)研究,要將知識(shí)連接成網(wǎng)。

自己給自己構(gòu)造一個(gè)場(chǎng)景,順著把用到的技術(shù)全部梳理一遍,能講出這個(gè)整體過(guò)程,有頭有尾,才能真的理解,比如hashmap插入數(shù)據(jù)的過(guò)程、threadlocal創(chuàng)建釋放的過(guò)程、String怎么實(shí)現(xiàn)的字符串拼接、SpringBoot框架搭建的每一步等等。


歡迎學(xué)編程的朋友們加入魚(yú)皮的,和上萬(wàn)名學(xué)編程的同學(xué)共享知識(shí)、交流進(jìn)步,學(xué)習(xí)原創(chuàng)項(xiàng)目并享有答疑指導(dǎo)服務(wù)。

往期推薦

相關(guān)稿件

騰訊面試體驗(yàn)倍兒好

康乃馨是送給什么人的(康乃馨花語(yǔ)和寓意)-環(huán)球報(bào)資訊

【全球新要聞】Soul發(fā)布《2023年輕人搭子社交報(bào)告》

每日熱門(mén):文化市集、星空音樂(lè)、夜觀昆蟲(chóng)……綠美白云生態(tài)嘉年華燃情夏夜

三消息:波爾津吉斯加盟綠軍,布朗拒絕球員選項(xiàng),步行者掘金新交易達(dá)成 今日關(guān)注

當(dāng)前熱議!浙江省養(yǎng)老金調(diào)整方案2023年(最新)將公布,6月還有一筆補(bǔ)貼已發(fā)放?

今頭條!iPhone16 無(wú)緣蘋(píng)果自研 5G 芯片

海信家電(00921)及一系列附屬認(rèn)購(gòu)合共16.3億元的浦銀理財(cái)產(chǎn)品|天天快資訊

環(huán)球短訊!圍城這本書(shū)主要講了什么

焦點(diǎn)簡(jiǎn)訊:奇葩,男子買(mǎi)早餐迷路 ,被困綠化帶四天三夜

金山云港股跌8.74%

新聞聯(lián)播丨成渝地區(qū)雙城經(jīng)濟(jì)圈累計(jì)完成重大項(xiàng)目投資超8400億元 天天播報(bào)

天天快播:生理鹽水敷臉后需洗嗎(過(guò)敏生理鹽水敷臉后需洗嗎)

世界觀焦點(diǎn):美元/日元行情綜述(2023年6月22日)

金力永磁(06680)委任梁敏輝及李曉光為非執(zhí)行董事

6月23~6月30有求必應(yīng),大富大貴,搖直上,財(cái)運(yùn)極佳的生肖

當(dāng)前熱門(mén):紙槍的折法 紙槍的折法可發(fā)子彈,威力大

環(huán)球今頭條!銀川燒烤店爆炸31人死亡,事發(fā)前細(xì)節(jié)公布

熱消息:李夢(mèng)與中國(guó)女籃在悉尼會(huì)合 本屆亞洲杯隊(duì)員全部到齊

B端落地先行:大模型助力 天天看熱訊

自治區(qū)農(nóng)業(yè)農(nóng)村廳召開(kāi)2022年度國(guó)家考核評(píng)估反饋問(wèn)題整改工作布置會(huì)議|當(dāng)前看點(diǎn)

澧縣:積極開(kāi)展“安全生產(chǎn)月”交通安全宣傳活動(dòng)

全球微頭條丨抖音:無(wú)相關(guān)資質(zhì)認(rèn)證用戶(hù) 不得使用具有誤導(dǎo)性的資訊類(lèi)賬號(hào)信息

【天天快播報(bào)】《中國(guó)國(guó)家地理》聯(lián)合高德發(fā)布“人生探索計(jì)劃” 可實(shí)現(xiàn)精品自駕路線(xiàn)一鍵導(dǎo)航

環(huán)球焦點(diǎn)!新加坡樟宜機(jī)場(chǎng)用機(jī)器人警察巡邏,美媒:它們不僅僅是噱頭

國(guó)產(chǎn)缺芯少屏問(wèn)題都被他解決了,京東方之父再次抓住新機(jī)遇 世界速看料

“云辦案”巧調(diào)解 萬(wàn)里對(duì)話(huà)化糾紛

房主難進(jìn)自家門(mén),解開(kāi)難題還需正本清源

微資訊!捷邁邦美在馬來(lái)西亞開(kāi)設(shè)新辦事處和GBS中心

高溫日歷出爐!北方多地將現(xiàn)今年來(lái)最長(zhǎng)連續(xù)高溫


主站蜘蛛池模板: 日韩久久久久久久久久久久久 | 日韩一区二区高清视频| 久久精品99无色码中文字幕| 日韩中文字幕在线观看| 日韩在线中文字幕| 国产一区二区精品在线| 日韩视频一区在线| 岛国一区二区三区高清视频| 欧美 日韩 国产 在线观看| 日韩在线一区二区三区免费视频| 国产福利久久| 国产精品入口免费视| 欧美亚洲日本在线观看| 日韩中文字幕在线免费观看| 91精品国产91久久| 成人中文字幕av| 国产精品国产亚洲伊人久久| 激情六月天婷婷| 久久久久久午夜| 久久另类ts人妖一区二区| 欧美高清视频一区| 欧美高清性xxxxhd| 欧美日韩精品综合| 欧美 日韩 国产 在线观看| 欧美精品一本久久男人的天堂| 日韩中文在线中文网三级| 亚洲v国产v在线观看| 国产成人av在线| 国产成人精品在线播放| 成人精品网站在线观看| www黄色av| 91av国产在线| 91精品成人久久| 亚洲欧洲国产精品久久| 91久久国产综合久久91精品网站| 国产精品 日韩| 国产一区二区视频在线免费观看| 狠狠色综合网站久久久久久久| 热久久这里只有精品| 欧洲精品在线一区| 欧美一区少妇|