你好,我是田哥
最新貓眼、阿里云、美團....面經(jīng)
有朋友私聊我,說昨天的這篇文章中,只給出了面試題,沒有答案,今天給安排一份貓眼面經(jīng)的參考答案。
在線刷題小程序
面試題
項目用到的技術(shù)棧、項目問的比較多,一定要多看
索引的數(shù)據(jù)結(jié)構(gòu)為什么要用b+樹?
1. 自我介紹
自我介紹主要包括三個部分:
個人基本信息、在校期間獲得過什么編程之類的講,獎學(xué)金之類的,在職期間做過哪些牛逼的項目,任職過項目經(jīng)歷、技術(shù)經(jīng)理等。
項目中遇到過什么比較難的問題,自己是怎么解決,總之就是說一些自己有亮點的東西,有數(shù)據(jù)說數(shù)據(jù)。說白了都是自己簡歷中精華的提煉。
一定要結(jié)尾,不然面試官不知道你的自我介紹是否結(jié)束。"以上是個人的基本情況,謝謝!"
2. 項目用到的技術(shù)棧、項目問的比較多,一定要多看
項目中的技術(shù)棧一定要搞清楚,用到了xx技術(shù),要知道為什么要用它,同時還要結(jié)合你的業(yè)務(wù)場景來說。很多人就是把之前的項目忘了,更不用說xx技術(shù)在項目中是用來干什么了。
所以,面試之前一定多看看簡歷中項目,不要到了面試官面前一問三不知。
3. 三次握手四次揮手
網(wǎng)絡(luò)通信的三次握手是指在建立TCP連接時,客戶端和服務(wù)器之間進行的一系列握手動作。具體步驟如下:
- 客戶端向服務(wù)器發(fā)送一個SYN(同步)請求,請求建立連接。
- 服務(wù)器收到請求后,向客戶端發(fā)送一個SYN-ACK(同步-確認)響應(yīng),表示接收到請求,并同意建立連接。
- 客戶端收到服務(wù)器的響應(yīng)后,再發(fā)送一個ACK(確認)響應(yīng),表示已經(jīng)收到服務(wù)器的確認,連接建立完成。
四次揮手是指在斷開TCP連接時,客戶端和服務(wù)器之間進行的一系列揮手動作。具體步驟如下:
- 客戶端向服務(wù)器發(fā)送一個FIN(結(jié)束)請求,表示不再發(fā)送數(shù)據(jù)。
- 服務(wù)器收到請求后,向客戶端發(fā)送一個ACK響應(yīng),表示已經(jīng)收到客戶端的請求。
- 服務(wù)器再發(fā)送一個FIN請求,表示服務(wù)器也不再發(fā)送數(shù)據(jù)。
- 客戶端收到服務(wù)器的請求后,向服務(wù)器發(fā)送一個ACK響應(yīng),表示已經(jīng)收到服務(wù)器的請求,連接斷開完成。
通過三次握手和四次揮手,客戶端和服務(wù)器可以建立和斷開連接,并保證數(shù)據(jù)的可靠傳輸。
4. 緩存穿透和雪崩的原因和解決方法
緩存穿透和雪崩是常見的緩存問題,它們的原因和解決方法如下:
緩存穿透:原因:當一個請求查詢一個不存在的數(shù)據(jù)時,由于緩存中沒有該數(shù)據(jù),每次請求都會穿透緩存直接查詢數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫壓力過大。解決方法:
- 布隆過濾器:使用布隆過濾器在緩存層面進行過濾,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,不存在的數(shù)據(jù)會被快速過濾掉。
- 空值緩存:對于查詢結(jié)果為空的數(shù)據(jù),也將其緩存起來,可以設(shè)置一個較短的過期時間,避免頻繁查詢數(shù)據(jù)庫。
緩存雪崩:原因:緩存中的大量數(shù)據(jù)同時過期或失效,導(dǎo)致大量請求直接訪問數(shù)據(jù)庫,造成數(shù)據(jù)庫壓力過大,甚至導(dǎo)致數(shù)據(jù)庫崩潰。解決方法:
- 緩存失效時間錯開:對于相同的緩存失效時間,可以在其基礎(chǔ)上添加一個隨機值,使緩存失效時間錯開,避免大量緩存同時過期。
- 熱點數(shù)據(jù)永不過期:對于一些熱點數(shù)據(jù),可以設(shè)置永不過期,確保這些數(shù)據(jù)一直在緩存中可用。
- 多級緩存:使用多級緩存架構(gòu),將緩存分為多個層級,不同層級的緩存設(shè)置不同的失效時間,避免緩存同時失效。
- 預(yù)熱:在系統(tǒng)低峰期,提前加載緩存,避免在高峰期突然大量請求導(dǎo)致緩存失效。
- 數(shù)據(jù)更新加鎖:在更新緩存時,使用分布式鎖來避免多個請求同時更新緩存,保證只有一個請求更新成功。
- 限流降級:在緩存失效時,限制對數(shù)據(jù)庫的直接訪問量,可以通過限流或者降級策略來減少對數(shù)據(jù)庫的壓力。
5. 布隆過濾器你了解嗎
布隆過濾器是一種用于判斷一個元素是否存在于集合中的數(shù)據(jù)結(jié)構(gòu),它通過使用多個哈希函數(shù)和位數(shù)組來實現(xiàn)。具體來說,布隆過濾器會將每個元素通過多個哈希函數(shù)映射到位數(shù)組中的多個位置,將對應(yīng)位置的位設(shè)置為1。當要判斷一個元素是否存在時,布隆過濾器會對該元素進行相同的哈希映射,然后查看對應(yīng)位置的位是否都為1,若都為1,則認為元素存在于集合中,若存在任一位為0,則認為元素不存在于集合中。
布隆過濾器的主要作用是在大規(guī)模數(shù)據(jù)集中快速判斷一個元素是否存在,常用于緩存系統(tǒng)、網(wǎng)絡(luò)爬蟲、垃圾郵件過濾等場景,可以有效地減少對底層存儲系統(tǒng)的查詢壓力。
布隆過濾器的優(yōu)點包括:
- 空間效率高:布隆過濾器只需要使用一個位數(shù)組和多個哈希函數(shù)來表示集合,相比使用傳統(tǒng)的哈希表或者樹等數(shù)據(jù)結(jié)構(gòu),布隆過濾器的空間占用更小。
- 查詢效率高:布隆過濾器通過多個哈希函數(shù)將元素映射到多個位置,所以查詢一個元素只需要進行幾次位操作,時間復(fù)雜度較低。
- 可擴展性好:布隆過濾器支持動態(tài)添加元素,可以根據(jù)需要進行擴展。
布隆過濾器的缺點包括:
- 存在一定的誤判率:由于多個元素可能映射到同一個位,所以當判斷一個元素是否存在時,存在一定的誤判率,即可能將不存在的元素誤判為存在。
- 不支持元素的刪除:由于多個元素可能映射到同一個位,所以無法準確地刪除一個元素,只能通過重新構(gòu)建布隆過濾器來實現(xiàn)。
總的來說,布隆過濾器是一種高效的數(shù)據(jù)結(jié)構(gòu),適用于對查詢效率要求較高、對誤判率能夠容忍的場景。
6. mysql中sql執(zhí)行流程
在MySQL中,SQL執(zhí)行流程通常包括以下幾個步驟:
語法解析:MySQL首先對輸入的SQL語句進行語法解析,檢查其是否符合MySQL的語法規(guī)范。
語義分析:在語義分析階段,MySQL會驗證SQL語句中的表、列等對象是否存在,以及用戶是否具有相應(yīng)的權(quán)限。
查詢優(yōu)化:如果是查詢語句,MySQL會對其進行優(yōu)化,選擇合適的執(zhí)行計劃來提高查詢性能。這個階段包括了索引選擇、連接順序優(yōu)化、子查詢優(yōu)化等。
執(zhí)行計劃生成:在查詢優(yōu)化階段完成后,MySQL會生成執(zhí)行計劃,決定如何執(zhí)行SQL語句。執(zhí)行計劃通常是一個樹形結(jié)構(gòu),包括了各個操作的順序、方式等。
執(zhí)行SQL語句:MySQL根據(jù)生成的執(zhí)行計劃開始執(zhí)行SQL語句,包括從磁盤讀取數(shù)據(jù)、進行過濾、排序、連接等操作。
返回結(jié)果:執(zhí)行完SQL語句后,MySQL將結(jié)果返回給客戶端。結(jié)果可以是查詢結(jié)果集、影響行數(shù)等。
需要注意的是,MySQL還有一些其他的優(yōu)化技術(shù)和功能,比如緩存、鎖機制等,這些也會對SQL執(zhí)行流程產(chǎn)生影響。此外,MySQL還支持批量執(zhí)行SQL語句、并行執(zhí)行等特性,以進一步提高執(zhí)行效率。
7. sqlserver你了解嗎,
SQL Server是由Microsoft開發(fā)的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),用于存儲和檢索數(shù)據(jù)。它支持廣泛的企業(yè)級應(yīng)用和數(shù)據(jù)分析任務(wù)。
SQL Server和MySQL是兩種不同的數(shù)據(jù)庫管理系統(tǒng),它們有以下幾點區(qū)別:
開發(fā)公司和許可:SQL Server是由Microsoft開發(fā)并擁有商業(yè)許可,而MySQL是由Oracle公司擁有商業(yè)許可的開源數(shù)據(jù)庫管理系統(tǒng)。
數(shù)據(jù)庫規(guī)模和性能:SQL Server通常被用于大型企業(yè)級應(yīng)用,它具有較大的數(shù)據(jù)處理能力和高性能特性。MySQL通常在中小型應(yīng)用中使用,但也可以應(yīng)對一些大型應(yīng)用需求。
數(shù)據(jù)庫功能:SQL Server提供了許多高級功能,如支持分布式事務(wù)處理、復(fù)制、數(shù)據(jù)倉庫和分析服務(wù)等。MySQL提供了基本的數(shù)據(jù)庫功能,但在某些高級功能上可能不如SQL Server。
數(shù)據(jù)庫語法和工具:SQL Server使用Transact-SQL(T-SQL)作為其查詢語言,而MySQL使用標準的SQL語言。此外,SQL Server提供了一套完整的集成開發(fā)環(huán)境(IDE)和管理工具,而MySQL提供了較為簡單的管理工具。
需要根據(jù)具體的需求和預(yù)算來選擇適合的數(shù)據(jù)庫管理系統(tǒng)。對于大型企業(yè)級應(yīng)用和需要高級功能的場景,SQL Server可能更適合;而對于中小型應(yīng)用和較為簡單的需求,MySQL可能更合適。
8. 二進制文件在mysql中的作用
在MySQL中,二進制文件具有以下作用:
存儲數(shù)據(jù):MySQL可以將二進制文件作為BLOB(Binary Large Object)類型的列存儲在數(shù)據(jù)庫中。這種類型的列可以用來存儲任意二進制數(shù)據(jù),如圖像、音頻、視頻等文件。
備份和恢復(fù):二進制文件可以用于備份和恢復(fù)數(shù)據(jù)庫。通過將數(shù)據(jù)庫的二進制日志文件備份,可以在需要時將數(shù)據(jù)庫恢復(fù)到特定的時間點。
數(shù)據(jù)復(fù)制:MySQL的二進制日志文件(binary log)記錄了數(shù)據(jù)庫的所有更改操作,包括插入、更新和刪除等。這些日志文件可以用于數(shù)據(jù)復(fù)制,將數(shù)據(jù)庫的更改操作同步到其他MySQL實例,實現(xiàn)數(shù)據(jù)的復(fù)制和高可用性。
數(shù)據(jù)恢復(fù):當數(shù)據(jù)庫發(fā)生故障或數(shù)據(jù)丟失時,可以使用二進制日志文件進行數(shù)據(jù)恢復(fù)。通過將二進制日志文件應(yīng)用到數(shù)據(jù)庫中,可以將數(shù)據(jù)庫恢復(fù)到故障發(fā)生之前的狀態(tài)。
需要注意的是,二進制文件在MySQL中是以二進制形式存儲的,無法直接查看和編輯。如果需要對二進制文件進行操作,可以通過應(yīng)用程序或工具來實現(xiàn)。
9. undolog和redolog的作用
在MySQL中,undolog和redolog是兩個重要的日志文件,用于確保數(shù)據(jù)庫的事務(wù)的持久性和一致性。
- 作用:記錄事務(wù)的修改操作,用于回滾(撤銷)事務(wù)。
- 存儲位置:在InnoDB存儲引擎中,undolog存儲在磁盤上的undolog文件中。
- 內(nèi)容:undolog記錄了事務(wù)執(zhí)行過程中對數(shù)據(jù)的修改操作,包括插入、更新和刪除操作。
- 使用方式:當事務(wù)需要回滾時,MySQL會根據(jù)undolog中的記錄,將數(shù)據(jù)恢復(fù)到事務(wù)開始之前的狀態(tài)。
- 作用:記錄事務(wù)的修改操作,用于保證事務(wù)的持久性。
- 存儲位置:在InnoDB存儲引擎中,redolog存儲在磁盤上的redolog文件中。
- 內(nèi)容:redolog記錄了事務(wù)執(zhí)行過程中對數(shù)據(jù)的修改操作,包括插入、更新和刪除操作。
- 使用方式:當事務(wù)提交時,MySQL會將redolog中的記錄刷新到磁盤上的數(shù)據(jù)文件中,以保證事務(wù)的持久性。
總結(jié):
- undolog用于回滾事務(wù),記錄了事務(wù)執(zhí)行過程中的修改操作;
- redolog用于保證事務(wù)的持久性,記錄了事務(wù)執(zhí)行過程中的修改操作;
- 兩者都是用于恢復(fù)和保護數(shù)據(jù)庫的重要日志文件。
10. java的基本數(shù)據(jù)類型
Java的基本數(shù)據(jù)類型包括以下幾種:
- 整數(shù)類型:byte、short、int、long
這些基本數(shù)據(jù)類型在Java中用于存儲不同類型的數(shù)據(jù),并具有不同的取值范圍和內(nèi)存占用大小。在使用這些數(shù)據(jù)類型時,需要根據(jù)具體的需求選擇合適的類型來存儲數(shù)據(jù)。
11. spring中ioc和aop你了解嗎
IOC(Inversion of Control)的原理和作用
IOC是一種設(shè)計模式,也是Spring框架的核心思想之一。它的原理是將對象的創(chuàng)建、依賴關(guān)系的管理交給容器來完成,而不是由程序員手動管理。通過IOC容器,我們可以將對象的創(chuàng)建和依賴注入的過程解耦,使得代碼更加靈活、可維護和可測試。
IOC
解耦:通過IOC容器管理對象的創(chuàng)建和依賴注入,將對象之間的耦合關(guān)系轉(zhuǎn)移到容器中,使得代碼更加靈活、可維護和可測試。
依賴注入:IOC容器負責將對象之間的依賴關(guān)系注入到對象中,使得對象之間可以松耦合地協(xié)作。
配置集中化:通過配置文件或注解的方式,將對象的創(chuàng)建和依賴關(guān)系的管理集中在一個地方,方便管理和維護。
AOP的基礎(chǔ):IOC容器是實現(xiàn)AOP(Aspect-Oriented Programming)的基礎(chǔ),可以通過IOC容器來管理切面和切點,實現(xiàn)橫切關(guān)注點的統(tǒng)一處理。
AOP(Aspect-Oriented Programming)的原理和作用
AOP是一種編程范式,它的原理是通過在不修改原有代碼的情況下,將橫切關(guān)注點(如日志、事務(wù)、安全等)與業(yè)務(wù)邏輯進行解耦,從而提高代碼的可維護性和可重用性。
AOP
解耦:AOP將橫切關(guān)注點與業(yè)務(wù)邏輯進行解耦,使得代碼更加清晰、可維護和可重用。
集中處理橫切關(guān)注點:通過AOP,我們可以將橫切關(guān)注點(如日志、事務(wù)、安全等)集中處理,避免代碼的重復(fù)編寫。
提高代碼的可維護性和可重用性:通過AOP,我們可以將橫切關(guān)注點的代碼抽取出來,使得代碼更加清晰、可維護和可重用。
動態(tài)代理:AOP的實現(xiàn)方式之一是通過動態(tài)代理,在運行時動態(tài)地生成代理對象,從而實現(xiàn)橫切關(guān)注點的統(tǒng)一處理。
總結(jié)來說,IOC和AOP是Spring框架的兩個核心特性。IOC通過將對象的創(chuàng)建和依賴注入交給容器來管理,實現(xiàn)了對象之間的解耦和依賴注入;AOP通過將橫切關(guān)注點與業(yè)務(wù)邏輯進行解耦,提高了代碼的可維護性和可重用性。兩者結(jié)合使用,可以更好地實現(xiàn)面向?qū)ο缶幊痰脑瓌t。
12. spring怎么樣解決循環(huán)依賴
在Spring中,當兩個或多個bean之間存在循環(huán)依賴時,可以通過以下幾種方式解決:
構(gòu)造函數(shù)注入:使用構(gòu)造函數(shù)注入可以解決循環(huán)依賴的問題。通過將依賴作為構(gòu)造函數(shù)的參數(shù)傳遞,可以確保在創(chuàng)建bean時,所有依賴的bean都已經(jīng)被實例化。
Setter方法注入:使用Setter方法注入也可以解決循環(huán)依賴的問題。通過在bean的Setter方法中注入依賴,可以確保在創(chuàng)建bean時,所有依賴的bean都已經(jīng)被實例化。
使用@Lazy注解:使用@Lazy注解可以延遲加載bean的實例化過程,從而解決循環(huán)依賴的問題。通過將@Lazy注解添加到bean的定義上,可以延遲實例化bean,直到第一次使用時才進行實例化。
使用@DependsOn注解:使用@DependsOn注解可以指定bean的依賴關(guān)系,從而解決循環(huán)依賴的問題。通過在bean的定義上添加@DependsOn注解,可以確保在創(chuàng)建bean時,所有依賴的bean都已經(jīng)被實例化。
需要注意的是,循環(huán)依賴可能會導(dǎo)致死鎖或無限遞歸的問題,因此在設(shè)計應(yīng)用程序時應(yīng)盡量避免循環(huán)依賴的出現(xiàn)。如果無法避免循環(huán)依賴,可以通過上述方法解決。
在Spring中,解決循環(huán)依賴是通過使用三級緩存(三個map)來實現(xiàn)的。具體原理如下:
- 創(chuàng)建對象A時,首先會檢查A是否在一級緩存中,如果在則直接返回A的實例。
- 如果A不在一級緩存中,則會創(chuàng)建一個A的早期引用,并將其放入二級緩存中。
- 接著,Spring會開始創(chuàng)建A對象的實例,并將其放入一級緩存中。
- 在創(chuàng)建A對象的過程中,如果發(fā)現(xiàn)A依賴于B,那么Spring會先去創(chuàng)建B對象。
- 創(chuàng)建B對象時,同樣會檢查B是否在一級緩存中,如果在則直接返回B的實例。
- 如果B不在一級緩存中,則會創(chuàng)建一個B的早期引用,并將其放入二級緩存中。
- 接著,Spring會開始創(chuàng)建B對象的實例,并將其放入一級緩存中。
- 在創(chuàng)建B對象的過程中,如果發(fā)現(xiàn)B又依賴于A,那么Spring會從二級緩存中獲取A的早期引用,并注入到B中。
- 當A和B的創(chuàng)建過程都完成后,Spring會將A和B的實例放入一級緩存中,并將二級緩存中的早期引用清除。
- 最后,Spring會將A和B的實例注入到彼此的屬性中,完成循環(huán)依賴的解決。
通過使用三級緩存,Spring能夠在對象創(chuàng)建過程中解決循環(huán)依賴的問題,保證對象的正確創(chuàng)建和注入。這種機制使得Spring能夠處理復(fù)雜的依賴關(guān)系,提高了應(yīng)用程序的靈活性和可維護性。
13. mysql中有哪些鎖
在MySQL中,常見的鎖包括以下幾種:
共享鎖(Shared Lock):也稱為讀鎖,多個事務(wù)可以同時持有共享鎖,用于保證讀操作的一致性。共享鎖之間不會互相阻塞,但會與排它鎖互斥。
排它鎖(Exclusive Lock):也稱為寫鎖,只有一個事務(wù)可以持有排它鎖,用于保證寫操作的原子性。排它鎖與其他任何鎖都互斥,包括共享鎖和排它鎖。
記錄鎖(Record Lock):用于保護單個記錄的鎖,可以是共享鎖或排它鎖。記錄鎖是在存儲引擎層實現(xiàn)的,不同的存儲引擎可能有不同的實現(xiàn)方式。
表鎖(Table Lock):鎖定整個表,可以是共享鎖或排它鎖。表鎖是在MySQL服務(wù)器層實現(xiàn)的,對整個表進行鎖定,會對其他事務(wù)的讀寫操作產(chǎn)生阻塞。
行鎖(Row Lock):也稱為行級鎖,用于保護表中的行數(shù)據(jù)。行鎖可以是共享鎖或排它鎖,不同的事務(wù)可以同時持有不同行的共享鎖,但只能有一個事務(wù)持有某一行的排它鎖。
需要注意的是,MySQL的鎖機制是基于存儲引擎實現(xiàn)的,不同的存儲引擎可能有不同的鎖實現(xiàn)方式。常見的存儲引擎包括InnoDB、MyISAM等,它們在鎖的粒度、并發(fā)性能等方面有所不同。
14. 鎖的是什么東西
在MySQL中,鎖是用于控制并發(fā)訪問的機制,用于保證數(shù)據(jù)的一致性和完整性。鎖可以應(yīng)用在不同的粒度上,包括表級鎖和行級鎖。
表級鎖是對整個表進行加鎖,當一個事務(wù)獲取了表級鎖后,其他事務(wù)無法對該表進行修改操作,只能進行讀取操作。表級鎖的優(yōu)點是簡單、粗粒度,但是并發(fā)性較差。
行級鎖是對表中的行進行加鎖,當一個事務(wù)獲取了某一行的鎖后,其他事務(wù)可以繼續(xù)對其他行進行操作,只有對同一行的操作會被阻塞。行級鎖的優(yōu)點是并發(fā)性好,但是實現(xiàn)相對復(fù)雜。
MySQL中的鎖可以分為共享鎖(讀鎖)和排他鎖(寫鎖)。共享鎖可以被多個事務(wù)同時獲取,用于讀取操作,不會阻塞其他事務(wù)的讀取操作。排他鎖只能被一個事務(wù)獲取,用于寫入操作,會阻塞其他事務(wù)的讀取和寫入操作。
鎖的使用需要根據(jù)具體的業(yè)務(wù)場景和并發(fā)訪問需求進行合理的設(shè)計和配置,以保證數(shù)據(jù)的一致性和并發(fā)性。
15. 線程和進程的區(qū)別
線程和進程是操作系統(tǒng)中的兩個重要概念,它們有以下區(qū)別:
定義:進程是程序的執(zhí)行實例,是操作系統(tǒng)進行資源分配和調(diào)度的基本單位;線程是進程中的一個執(zhí)行單元,是操作系統(tǒng)進行調(diào)度和執(zhí)行的基本單位。
資源占用:進程擁有獨立的地址空間、文件描述符、堆棧等資源,相互之間不共享;線程與所屬進程共享地址空間和其他資源,線程之間可以直接訪問同一進程的數(shù)據(jù)。
切換開銷:進程切換需要保存和恢復(fù)整個進程的上下文,開銷較大;線程切換只需要保存和恢復(fù)線程的上下文,開銷較小。
通信和同步:進程之間通信需要使用進程間通信(IPC)機制,如管道、消息隊列、共享內(nèi)存等;線程之間通信可以直接讀寫共享變量,同步可以使用互斥鎖、條件變量等機制。
獨立性:進程是獨立的執(zhí)行實體,擁有自己的執(zhí)行狀態(tài)和控制流;線程是進程的一部分,共享進程的資源,執(zhí)行狀態(tài)和控制流與所屬進程相互依賴。
總結(jié)來說,進程是資源分配的基本單位,線程是執(zhí)行調(diào)度的基本單位。進程之間相互獨立,線程之間共享資源。進程切換開銷大,線程切換開銷小。進程間通信需要使用IPC機制,線程間通信可以直接讀寫共享變量。
16. 線程的幾種狀態(tài)
在Java中,線程有以下幾種狀態(tài):
新建(New):當線程對象被創(chuàng)建時,它處于新建狀態(tài)。此時線程還沒有開始執(zhí)行。
運行(Runnable):當調(diào)用線程的start()方法后,線程進入運行狀態(tài)。此時線程正在執(zhí)行任務(wù)。
阻塞(Blocked):當線程被阻塞時,它暫時停止執(zhí)行。線程可能會進入阻塞狀態(tài)的原因有多種,比如等待某個資源、等待輸入/輸出等。
等待(Waiting):線程進入等待狀態(tài)是因為調(diào)用了Object類的wait()方法、Thread類的join()方法或LockSupport類的park()方法。在等待狀態(tài)下,線程會釋放持有的鎖。
超時等待(Timed Waiting):線程進入超時等待狀態(tài)是因為調(diào)用了Thread類的sleep()方法、Object類的wait(long timeout)方法、Thread類的join(long millis)方法或LockSupport類的parkNanos()方法。
終止(Terminated):線程執(zhí)行完任務(wù)后,或者因異常而結(jié)束,線程進入終止狀態(tài)。
以上就是Java中線程的幾種狀態(tài)。
17. 怎么樣能使線程進入阻塞狀態(tài)
可以使用以下方法使線程進入阻塞狀態(tài):
使用Thread類的sleep()
方法:調(diào)用Thread.sleep()
方法可以使當前線程進入阻塞狀態(tài),指定的時間內(nèi)不會執(zhí)行任何操作。例如,Thread.sleep(1000)
將使當前線程阻塞1秒鐘。
使用Object類的wait()
方法:調(diào)用wait()
方法可以使當前線程進入阻塞狀態(tài),并釋放對象的鎖。其他線程可以通過調(diào)用相同對象的notify()
或notifyAll()
方法來喚醒被阻塞的線程。
使用Thread類的join()
方法:調(diào)用join()
方法可以使當前線程等待另一個線程執(zhí)行完畢后再繼續(xù)執(zhí)行。例如,thread.join()
將使當前線程阻塞,直到thread
線程執(zhí)行完畢。
使用Lock類的lock()
方法:通過使用Lock類的lock()
方法獲取鎖,可以使線程進入阻塞狀態(tài),直到獲取到鎖為止。例如,lock.lock()
將使當前線程阻塞,直到獲取到鎖。
以上是幾種常見的使線程進入阻塞狀態(tài)的方法。根據(jù)具體的需求和場景,選擇適合的方法來實現(xiàn)線程的阻塞。
18. wait()和sleep()的區(qū)別
wait()
和sleep()
是兩個不同的方法,wait()
方法是Object中的,sleep()
是Thread中的。都是用于控制程序的執(zhí)行。
wait()
方法是用于線程間通信的,它會使當前線程進入等待狀態(tài),直到子線程結(jié)束或收到指定的信號。在等待期間,當前線程會被掛起,不會占用CPU資源。
sleep()
函數(shù)是用于線程間的延時操作,它會使當前線程進入睡眠狀態(tài),暫停執(zhí)行一段指定的時間。在睡眠期間,當前線程會被掛起,不會占用CPU資源。
總結(jié)來說,wait()
是用于線程間通信,而sleep()
是用于線程間的延時操作。
20. 類的加載的過程
JVM中類的加載過程可以分為以下幾個步驟:
加載(Loading):將類的字節(jié)碼文件加載到內(nèi)存中。這個過程可以通過類加載器(ClassLoader)來完成。類加載器會根據(jù)類的全限定名(包括包名和類名)來查找并加載對應(yīng)的字節(jié)碼文件。
驗證(Verification):驗證字節(jié)碼文件的正確性和安全性。這個過程會檢查字節(jié)碼文件的結(jié)構(gòu)是否符合規(guī)范,并且會進行一些靜態(tài)分析,以確保字節(jié)碼文件不會引發(fā)安全問題。
準備(Preparation):為類的靜態(tài)變量分配內(nèi)存,并設(shè)置默認初始值。在這個階段,JVM會為類的靜態(tài)變量分配內(nèi)存空間,并根據(jù)變量的類型設(shè)置默認的初始值(例如,int類型的變量默認為0)。
解析(Resolution):將符號引用解析為直接引用。在Java中,類之間的引用是通過符號引用來表示的,而在解析階段,JVM會將這些符號引用解析為直接引用,以便后續(xù)的訪問和調(diào)用。
初始化(Initialization):執(zhí)行類的初始化代碼。在這個階段,JVM會執(zhí)行類的靜態(tài)初始化代碼,包括靜態(tài)變量的賦值和靜態(tài)代碼塊的執(zhí)行。類的初始化是在類第一次被使用時觸發(fā)的,例如創(chuàng)建類的實例、訪問類的靜態(tài)變量或調(diào)用類的靜態(tài)方法。
使用(Usage):使用類的實例或調(diào)用類的方法。在類被初始化之后,就可以使用類的實例或調(diào)用類的方法了。
卸載(Unloading):卸載不再使用的類。當一個類不再被引用,并且沒有任何活動的實例時,JVM會卸載該類,釋放相關(guān)的內(nèi)存空間。
以上就是JVM中類的加載過程的主要步驟。
21. 說一說雙親委派機制
JVM中的雙親委派機制是一種類加載機制,它的目的是保證Java類的安全性和一致性。在雙親委派機制下,當一個類加載器收到加載類的請求時,它首先會將這個請求委派給它的父類加載器去完成,只有當父類加載器無法完成加載時,才會由當前類加載器自己去加載。
這種機制的好處在于可以避免類的重復(fù)加載,保證類的唯一性。當一個類加載器收到加載類的請求時,它會首先向上委派給父類加載器,如果父類加載器能夠找到并加載這個類,那么就直接返回這個類的Class對象;如果父類加載器無法找到這個類,那么子類加載器才會嘗試自己去加載。
雙親委派機制的具體實現(xiàn)是通過ClassLoader類的loadClass()方法來實現(xiàn)的。在loadClass()方法中,首先會檢查是否已經(jīng)加載過該類,如果已經(jīng)加載過,則直接返回已加載的Class對象;如果沒有加載過,則會調(diào)用父類加載器的loadClass()方法來嘗試加載,如果父類加載器加載失敗,則會調(diào)用自己的findClass()方法來加載類。
總結(jié)來說,雙親委派機制保證了類的加載順序,從而保證了類的唯一性和一致性。它的核心思想是"上級加載器優(yōu)先",即優(yōu)先使用父類加載器來加載類,只有在父類加載器無法加載時才由子類加載器來加載。這種機制有效地避免了類的重復(fù)加載和沖突,提高了系統(tǒng)的安全性和穩(wěn)定性。
22. int占多少字節(jié),最大為多少
在Java中,int類型占據(jù)4個字節(jié)(32位),可以表示的最大值為2^31-1,即2147483647。
23. 單例模式知道嗎?單例模式里的雙重檢查?
下面寫一個單例模式(面試中,可能會要你現(xiàn)場寫一個)
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
單例模式是一種創(chuàng)建型設(shè)計模式,它確保一個類只有一個實例,并提供一個全局訪問點。
雙重檢查鎖定(Double-Checked Locking)是一種在多線程環(huán)境下使用的延遲初始化的優(yōu)化技術(shù)。在單例模式中,雙重檢查鎖定用于確保只有一個實例被創(chuàng)建。
雙重檢查鎖定的優(yōu)點:
- 提供了延遲初始化,只有在需要時才會創(chuàng)建實例,節(jié)省了系統(tǒng)資源。
- 在多線程環(huán)境下保證了只有一個實例被創(chuàng)建,提高了性能。
雙重檢查鎖定的缺點:
- 實現(xiàn)復(fù)雜,需要考慮線程安全性和可見性。
- 在早期的JDK版本中,由于指令重排序的問題,可能會導(dǎo)致多個線程同時通過第一個null檢查,從而創(chuàng)建多個實例。但在JDK5及以后的版本中,通過使用volatile關(guān)鍵字修飾instance變量,可以解決這個問題。
總結(jié):雙重檢查鎖定是一種常用的單例模式實現(xiàn)方式,它在多線程環(huán)境下保證了只有一個實例被創(chuàng)建,并提供了延遲初始化的優(yōu)化。但需要注意在實現(xiàn)時要考慮線程安全性和可見性的問題。
24. hashmap如何解決哈希沖突問題?
HashMap使用了鏈地址法來解決哈希沖突問題。當發(fā)生哈希沖突時,即不同的鍵映射到了相同的哈希桶位置,HashMap會在該位置上維護一個鏈表或紅黑樹(JDK8之后),將具有相同哈希值的鍵值對存儲在同一個桶中。
當需要插入一個鍵值對時,HashMap會先計算鍵的哈希值,然后根據(jù)哈希值找到對應(yīng)的桶。如果桶中已經(jīng)存在鍵值對,則會遍歷鏈表或紅黑樹,找到對應(yīng)的鍵值對進行更新。如果桶中不存在鍵值對,則直接將新的鍵值對插入到桶中。
在查找鍵值對時,HashMap會根據(jù)鍵的哈希值找到對應(yīng)的桶,然后遍歷鏈表或紅黑樹,找到對應(yīng)的鍵值對進行返回。
通過使用鏈地址法,HashMap能夠高效地解決哈希沖突問題,并且在大部分情況下,插入、查找和刪除操作的時間復(fù)雜度都是O(1)。但是在極端情況下,如果哈希函數(shù)設(shè)計不好或者哈希沖突過多,可能會導(dǎo)致鏈表過長,從而降低HashMap的性能。為了解決這個問題,JDK8之后的HashMap引入了紅黑樹,當鏈表長度超過一定閾值時,會將鏈表轉(zhuǎn)換為紅黑樹,進一步提高了性能。
25. https你了解嗎?
HTTPS是一種用于安全傳輸數(shù)據(jù)的協(xié)議,它在HTTP的基礎(chǔ)上加入了SSL/TLS加密機制。
優(yōu)點:
- 數(shù)據(jù)傳輸安全:HTTPS使用SSL/TLS加密機制對數(shù)據(jù)進行加密,可以有效防止數(shù)據(jù)被竊取或篡改。
- 身份驗證:HTTPS使用數(shù)字證書對網(wǎng)站進行身份驗證,確保用戶訪問的是真實的網(wǎng)站,防止中間人攻擊。
- 改善搜索引擎排名:搜索引擎會優(yōu)先顯示使用HTTPS的網(wǎng)站,因為HTTPS可以提供更安全的用戶體驗。
- 保護用戶隱私:HTTPS可以隱藏用戶的瀏覽歷史和個人信息,提供更好的隱私保護。
缺點:
- 性能損耗:由于加密和解密的過程會增加服務(wù)器和客戶端的計算負載,HTTPS的性能相對于HTTP會有所下降。
- 部署和維護成本高:為了使用HTTPS,網(wǎng)站需要購買數(shù)字證書并進行配置,這會增加網(wǎng)站的部署和維護成本。
- CDN緩存問題:HTTPS的加密機制會導(dǎo)致內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)無法緩存網(wǎng)站的內(nèi)容,影響網(wǎng)站的訪問速度。
總的來說,HTTPS在保護數(shù)據(jù)安全和用戶隱私方面具有明顯優(yōu)勢,但也存在一些性能和成本方面的缺點。在需要保護敏感信息的場景下,使用HTTPS是非常重要的。
26. 索引失效的原因?
MySQL索引失效的原因有以下幾個:
索引列未被查詢條件使用:當查詢條件中沒有使用到索引列時,MySQL無法利用索引進行快速查找,導(dǎo)致索引失效。
索引列使用了函數(shù)或表達式:如果查詢條件中的索引列使用了函數(shù)或表達式,MySQL無法直接使用索引進行查找,而是需要對每一行數(shù)據(jù)進行計算,導(dǎo)致索引失效。
索引列上存在類型轉(zhuǎn)換:如果查詢條件中的索引列與索引的數(shù)據(jù)類型不一致,MySQL會進行類型轉(zhuǎn)換,導(dǎo)致索引失效。
索引列上存在范圍查詢:當查詢條件中的索引列使用了范圍查詢(例如大于、小于、區(qū)間等),MySQL只能使用索引的一部分進行查找,導(dǎo)致索引失效。
索引列上存在排序:如果查詢條件中的索引列需要進行排序操作,MySQL無法直接使用索引進行排序,而是需要額外的排序操作,導(dǎo)致索引失效。
索引列上存在模糊查詢:當查詢條件中的索引列使用了模糊查詢(例如LIKE操作),MySQL無法直接使用索引進行查找,而是需要對每一行數(shù)據(jù)進行匹配,導(dǎo)致索引失效。
索引列上存在NULL值:如果查詢條件中的索引列包含NULL值,MySQL無法使用索引進行查找,導(dǎo)致索引失效。
為了避免索引失效,需要根據(jù)具體的查詢場景進行優(yōu)化,例如合理設(shè)計索引、避免使用函數(shù)或表達式、避免類型轉(zhuǎn)換、避免范圍查詢、避免排序操作、避免模糊查詢等。
27. 索引的數(shù)據(jù)結(jié)構(gòu)為什么要用b+樹?
MySQL索引的數(shù)據(jù)結(jié)構(gòu)選擇B+樹的原因有以下幾點:
有序性:B+樹是一種有序的數(shù)據(jù)結(jié)構(gòu),可以快速進行范圍查詢和排序操作。在數(shù)據(jù)庫中,索引的主要作用是提高查詢效率,而B+樹的有序性能夠很好地支持這一點。
平衡性:B+樹是一種自平衡的樹結(jié)構(gòu),能夠保持樹的高度相對較低,從而減少磁盤I/O操作。在數(shù)據(jù)庫中,磁盤I/O是一個相對較慢的操作,通過使用B+樹可以減少磁盤I/O的次數(shù),提高查詢效率。
可擴展性:B+樹的結(jié)構(gòu)可以很容易地進行擴展和調(diào)整,適應(yīng)數(shù)據(jù)的動態(tài)變化。在數(shù)據(jù)庫中,數(shù)據(jù)的插入、刪除和更新是常見的操作,B+樹的可擴展性能夠很好地支持這些操作。
支持多級索引:B+樹的結(jié)構(gòu)可以很容易地支持多級索引,即通過多個索引字段進行查詢。在數(shù)據(jù)庫中,多級索引可以提高查詢的精確度和效率。
綜上所述,B+樹作為一種有序、平衡、可擴展且支持多級索引的數(shù)據(jù)結(jié)構(gòu),非常適合作為MySQL索引的數(shù)據(jù)結(jié)構(gòu)。它能夠提高查詢效率、減少磁盤I/O操作,并且能夠適應(yīng)數(shù)據(jù)的動態(tài)變化。
28. coding:二分查找,分析邊界問題
下面是一個用Java實現(xiàn)的二分查找的示例代碼:
public class BinarySearch {
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9};
int target = 5;
int result = binarySearch(arr, target);
if (result == -1) {
System.out.println("Element not found");
} else {
System.out.println("Element found at index " + result);
}
}
}
在這個示例中,binarySearch
方法接受一個已排序的整數(shù)數(shù)組和一個目標值作為參數(shù),然后使用二分查找算法在數(shù)組中查找目標值。如果找到目標值,則返回其索引;如果未找到目標值,則返回-1。
關(guān)于邊界問題,二分查找算法的邊界問題主要包括以下幾個方面:
數(shù)組為空:在開始二分查找之前,需要先判斷數(shù)組是否為空,如果為空,則直接返回-1。
數(shù)組長度為0或1:如果數(shù)組長度為0,則直接返回-1;如果數(shù)組長度為1,且該元素不等于目標值,則也直接返回-1。
目標值小于數(shù)組中的最小值或大于數(shù)組中的最大值:在二分查找過程中,如果目標值小于數(shù)組中的最小值或大于數(shù)組中的最大值,則說明目標值不在數(shù)組中,直接返回-1。
以上是對二分查找算法邊界問題的分析。在實際編寫代碼時,我們需要考慮這些邊界情況,并進行相應(yīng)的處理,以確保算法的正確性和健壯性。