面試整理八股

守漠待花开發表於2024-06-28

1、String為什麼是不可變的,有什麼好處

1、因為String類下的value陣列是用final修飾的,final保證了value一旦被初始化,就不可改變其引用。此外,成員變數的訪問許可權為 private,同時沒有提供方法將欄位暴露出來,想要修改只能透過 String 提供的方法。而且,String類是用final修飾的,不可以被繼承。

2、①安全性。 不可變性確保String物件的值在建立後不能被修改。所以可以經常用於儲存一些敏感資訊,例如使用者名稱、密碼、網路連線等。

②節省空間——字串常量池 透過使用常量池,內容相同的字串可以使用同一個物件,從而節省記憶體空間。

③執行緒安全 String 物件是不可修改的,如果執行緒嘗試修改 String 物件,會建立新的 String,所以不存在併發修改同一個物件的問題

④效能 String 被廣泛應用於 HashMap、HashSet 等雜湊類中,當對這些雜湊類進行操作時,例如 HashMap 的 get/put,hashCode 會被頻繁呼叫。由於不可變性,String 的 hashCode 只需要計算1次後就可以快取起來,因此在雜湊類中使用 String 物件可以提升效能。

2、sychronized和locked的區別?

1、synchronized是一個關鍵字而lock是一個介面

2、synchronized是隱式的加鎖,lock是顯示的加鎖。

3、synchronized可以作用在方法和程式碼塊上,而lock只能作用在程式碼塊上。

4、synchronized採用的是monitor物件監視器,lock的底層原理是AQS。

5、synchronized是非公平鎖,而lock可以是公平鎖也可以是非公平鎖。

6、synchronized用object的notify / notifyAll方法進行喚醒,而lock用condition進行喚醒。

3、介面和抽象類的區別?

1、抽象類只能單繼承而介面可以多實現。

2、抽象類可以有構造方法而介面中不能有構造方法。

3、抽象類中可以有成員變數而介面中沒有成員變數只有常量(public static final)。

4、抽象類中可以包含非抽象方法;在Java7之前介面中的所有方法都是抽象的,在Java8之後介面支援非抽象方法:default方法、靜態方法等。Java9支援私有方法、私有靜態方法。

5、抽象類中的方法型別可以是任意修飾符;Java8之前介面中的方法只能是public,Java9支援private型別。

4、Redis的基本資料型別?

字串String、雜湊表Hash、列表List、集合Set、有序集合Zset。

(1)字串String:可以用來做最簡單的資料,可以快取某個簡單的字串,也可以快取某個json格式的字串,Redis分散式鎖的實現就利用了這種資料結構,還包括可以實現計數器、Session共享、分散式ID。

(2)雜湊表Hash:可以用來儲存一些key-value對,更適合用來儲存物件。

(3)列表List:透過命令的組合,既可以當作棧,也可以當作佇列來使用,可以用來快取類似微信公眾號、微博等訊息流資料。

(4)集合Set(String字串型別的無序集合):和列表類似,也可以儲存多個元素,但是不能重複,集合可以進行交集、並集、差集操作,從而可以實現類似,我和某人共同關注的人、朋友圈點贊等功能。

(5)有序集合Zset(Zset是String型別的有序集合):不可重複,有序集合中的每個元素都需要指定一個分數,根據分數對元素進行升序排序。

5、Java的基礎資料型別?

boolean、byte、char、int、short、long、float、double

6、SpringMVC的實現邏輯?

首先DispatcherServlet會接收到request請求資訊,去頭去尾得到對映地址,然後透過HandlerMapping查詢到具體處理的Controller以及對應的方法。方法結束後會返回一個ModelAndView,裡面包含的是返回的資料以及返回的檢視。這個就會交給ViewResolver來處理。處理結束後就會跳轉到相應的檢視。

7、SpringBoot如何實現依賴注入?

1、使用 XML 配置依賴注入 在 Spring Boot 中,使用 XML 配置依賴注入(DI)時,需要使用<bean>元素來定義 bean,並使用<property>元素來為 bean 的屬性注入值或依賴物件。

2、使用 Java 配置類實現依賴注入(推薦) 使用 Java Config 實現依賴注入可以透過@Configuration和@Bean註解來實現。

3、使用註解來進行依賴注入(推薦) 可以使用註解來進行依賴注入,常用的註解有@Autowired和@Qualifier。

8、為什麼MySQL選擇B+樹索引?

1、階數更多,路徑更短。

2、磁碟讀寫程式碼B+樹更低,非葉子節點只儲存指標,葉子節點儲存資料。

3、B+樹便於掃庫和區間查詢,葉子節點是一個雙向連結串列。

9、where和having的區別?

SELECT customer_id, SUM(total_price) AS total FROM orders GROUP BY customer_id HAVING SUM(total_price) > 100;

1、WHERE 子句用於在執行查詢之前篩選行,而 HAVING 子句用於在執行聚合查詢後篩選結果集。

2、WHERE 出現在 FROM 子句之後,GROUP BY 子句之前;而 HAVING 出現在 GROUP BY 子句之後、ORDER BY 子句之前。

3、WHERE 可以使用比較運算子和邏輯運算子來指定過濾條件,而 HAVING 不僅可以使用比較運算子和邏輯運算子,還可以使用聚合函式。

10、什麼是執行緒池?

執行緒池是一種併發程式設計的機制,用於管理和複用執行緒,以提高程式的效能和資源利用率。在多執行緒環境中,頻繁地建立和銷燬執行緒會帶來較大的開銷,而執行緒池透過事先建立一組執行緒並將它們置於待命狀態,有效地減少了這種開銷。

11、hashmap擴容介紹,什麼時候開始擴容?

預設初始容量是16。HashMap的容量必須是2的N次方,HashMap會根據傳入的容量計算一個大於等於該容量的最小的2的N次方。

(1)當HashMap中的元素數量達到容量乘以載入因子時,就會觸發擴容操作。載入因子預設為0.75,可以透過構造方法設定。

(2)當需要擴容時,HashMap 會建立一個新的陣列,其大小為原陣列的兩倍。

(3)對於原陣列中的每個非空位置(即儲存了鍵值對的位置),會重新計算它們在新陣列中的位置。重新計算的方法是透過對原位置的雜湊值取模新陣列長度。

(4)對於每個原陣列的位置,如果它的連結串列長度小於等於閾值(預設為8),則直接將連結串列中的鍵值對按照順序放入新陣列的相應位置。如果連結串列長度超過閾值,會將該連結串列轉化為紅黑樹,然後再將紅黑樹的節點按照順序放入新陣列的相應位置。

(5)當陣列中的所有元素都被放入新的位置後,新陣列取代了原來的陣列,成為新的儲存結構。

(6)擴容操作完成後,原陣列會被垃圾回收。

12、Redis是單執行緒的,但是為什麼還那麼快?

1、完全基於記憶體的,C語言編寫。

2、採用單執行緒,避免不必要的上下文切換可競爭條件。

3、Redis透過I/O多路複用程式來監聽來自客戶端的大量連線,它會將感興趣的事件及型別註冊到核心中並監聽每個事件是否發生。I/O多路複用技術的使用讓Redis不需要額外建立多餘的執行緒來監聽客戶端的大量連線,降低了資源的消耗。

I/O多路複用是指利用單個執行緒來同時監聽多個Socket,並在某個Socket可讀、可寫時得到通知,從而避免無效的等待,充分利用CPU資源。目前的I/O多路複用都是採用的epoll模式實現,它會在通知使用者程序Socket就緒的同時,把已就緒的Socket寫入使用者空間,不需要挨個遍歷Socket來判斷是否就緒,提升了效能。

13、Redis記憶體淘汰策略?

(1)全域性的鍵空間選擇性移除。

(2)設定過期時間的鍵空間選擇性移除 。

比如移除最近最少使用的key、隨機移除某個key、優先移除更早過期的key呀(具體的看md文件)

14、類載入流程?

類載入的過程包括:載入、驗證、準備、解析、初始化、使用、解除安裝,其中驗證、準備、解析統稱為連線。

(1)載入:透過一個類的全限定名來獲取定義該類的二進位制位元組流,在記憶體中生成一個代表這個類的java.lang.Class物件。

(2)驗證:確保Class檔案的位元組流中包含的資訊符合當前虛擬機器的要求,並且不會危害虛擬機器自身的安全。

(3)準備:為靜態變數分配記憶體並設定靜態變數初始值,這裡所說的初始值“通常情況”下是資料型別的零值。

(4)解析:將常量池內的符號引用替換為直接引用。

(5)初始化:到了初始化階段,才真正開始執行類中定義的Java初始化程式程式碼。主要是靜態變數賦值動作和靜態語句塊(static{})中的語句。

(6)使用:JVM開始從入口方法開始執行使用者的程式程式碼。

(7)解除安裝:當使用者程式程式碼執行完畢後,JVM便開始銷燬建立的Class物件。

15、jvm記憶體區域,虛擬機器棧裡面是什麼,堆裡面的資料什麼時候進入老年代?

Java虛擬機器棧: 執行緒私有的,每個執行緒都有一個私有的Java虛擬機器棧,用於儲存方法呼叫的區域性變數、運算元棧、動態連結、方法出口等資訊。每個方法的呼叫都會建立一個棧幀,方法執行完畢後棧幀會被銷燬。如果執行緒請求的棧深度大於虛擬機器允許的深度,將丟擲棧溢位異常。 堆:用於儲存物件例項和陣列。

①Young GC後,如果物件太大無法進入Survivor區,則會透過分配擔保機制進入老年代。

②物件每在Survivor區中“熬過”一次Young GC,年齡就增加1歲,當它的年齡增加到一定程度(預設為15歲,可以透過-XX:MaxTenuringThreshold設定),就將會被晉升到老年代中。

16、程式計數器是幹什麼的?

程式計數器:用於儲存當前執行緒執行的位元組碼指令的地址。在多執行緒環境下,每個執行緒都有自己獨立的程式計數器,以保證執行緒切換後能恢復到正確的執行位置。

17、方法執行的時候棧裡面是怎麼樣的?

每個方法的呼叫都會建立一個棧幀,方法執行完畢後棧幀會被銷燬。如果執行緒請求的棧深度大於虛擬機器允許的深度,將丟擲棧溢位異常。

18、方法區?

方法區:存放已被載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼資料,即永久代。在jdk1.8中不存在方法區了,被元空間替代了,原方法區被分成兩部分;1:載入的類資訊,2:執行時常量池;載入的類資訊被儲存在元空間中,執行時常量池儲存在堆中;

19、synchronize怎麼用的,原理?

synchronized的底層實現主要區分:程式碼塊和方法。

1、synchronized修飾程式碼塊時,編譯後會生成 monitorenter和monitorexit指令,分別對應進入同步塊和退出同步塊。會有兩個monitorexit,這是因為編譯時JVM為程式碼塊新增隱式的try-finally,在finally中進行了鎖釋放,這也是為什麼synchronized不需要手動釋放鎖的原因。

2、synchronized修飾方法時,編譯後會生成ACC_SYNCHRONIZED標記,當方法呼叫時,呼叫指令將會檢查方法的 ACC_SYNCHRONIZED訪問標誌是否被設定,如果設定了則會先嚐試獲得鎖。 兩種實現其實本質上沒有區別,只是方法的同步是一種隱式的方式來實現,無需透過位元組碼來完成。

20、TCP的三次握手?

在建立TCP連線時,需要透過三次握手來建立,過程是:

(1)客戶端向伺服器端傳送一個SYN;

(2)服務端接收到SYN後,給客戶端發 送一個SYN_ACK;

(3)客戶端接收到SYN_ACK後,再給服務端傳送一個ACK。

21、TCP的四次揮手?

在斷開TCP連線時,需要透過四次揮手來斷開,過程是:

(1)客戶端向服務端傳送FIN;

(2)服務端接收FIN後,向客戶端傳送ACK,表示我接收到了斷開連線的請求,客戶端可以不發資料了,不過服務端這邊可能還有資料正在處理;

(3)服務端處理完所有資料後,向客戶端傳送FIN,表示服務端現在可以斷開連線;

(4)客戶端接收到服務端的FIN,向服務端傳送ACK,表示客戶端也會斷開連線。

22、瀏覽器輸入URL的過程?

(1)DNS解析。

(2)建立TCP連線。

(3)傳送HTTP請求。

(4)伺服器處理請求並返回HTTP報文。

(5)瀏覽器解析渲染頁面。

(6)連線結束。

23、hashmap用了哪些資料結構?

在JDK1.7 中,由“陣列+連結串列”組成,陣列是 HashMap 的主體,連結串列則是主要為了解決雜湊衝突而存在的。 在jdk1.8版本後,底層是由“陣列+連結串列+紅黑樹”組成。java對HashMap做了改進,在連結串列長度大於8的時候,將後面的資料存在紅黑樹中,以加快檢索速度。

24、連結串列轉紅黑樹的目的?

為了加快檢索速率。紅黑樹雖然本質上是一顆二叉樹,但它在二叉查詢樹的基礎上增加了著色和相關的性質使得紅黑樹相對平衡,從而保證了紅黑樹的查詢、插入、刪除的時間複雜度最壞為O(log n)。

25、hashmap是執行緒安全的嗎?

HashMap在併發場景中不是執行緒安全的。比如A希望插入一個key-value對到HashMap中,當獲取到對應的連結串列結點位置時,此時執行緒A的時間片用完了,而此時執行緒B被排程得以執行,可能執行緒B佔用了A計算得到的位置,插入了數值。而執行緒A被切換回來的時候,不知道B已經插入了元素,仍然將元素插入此前計算好的位置,這樣就會將B執行緒的插入記錄覆蓋掉了,這對應了多執行緒的put可能導致元素的丟失;

JDK1.7 當擴容的時候,存在 Entry 鏈死迴圈和資料丟失問題(執行緒1的put和執行緒2的get併發,可能導致get為null) JDK 1.8 HashMap 採用陣列 + 連結串列 + 紅黑二叉樹的資料結構,最佳化了 1.7 中陣列擴容的方案,解決了 Entry 鏈死迴圈和資料丟失問題。但是多執行緒背景下,put 方法存在資料覆蓋的問題。

26、hash的過程?

HashMap中採用的鏈地址法解決hash衝突。

儲存索引是怎麼計算的:首先根據key的值計算出hashcode的值,然後根據hashcode計算出hash值,最後透過hash &(length-1)計算得到儲存的位置。

27、多執行緒下使用hashmap保證執行緒安全的方案?

1、HashTable 是執行緒安全的。HashTable 容器使用 synchronized 來保證執行緒安全,但線上程競爭激烈的情況下 HashTable 的效率非常低下。

2、①使用ConcurrentHashMap ,分段鎖的思想,將 HashMap 進行切割,把 HashMap 中的雜湊陣列切分成小陣列,每個小陣列有 n 個 HashEntry 組成,其中小陣列繼承自ReentrantLock(可重入鎖),這個小陣列名叫Segment(JDK1.7)。

②JDK1.8中取消了Segment 分段鎖,採用 CAS + synchronized 來保證併發安全,ConcurrentHashMap 中 synchronized 只鎖定當前連結串列或紅黑二叉樹的首節點,只要節點 hash 不衝突,就不會產生併發。

28、聊一聊concurrentHashMap?

concurrentHashMap是一種執行緒安全的高效Map集合,它是【執行緒安全】的雜湊表。它是透過“分段鎖”來實現多執行緒下的安全問題。

1、底層資料結構 jdk1.7採用分段陣列+連結串列實現 jdk1.8採用陣列+連結串列/紅黑樹。

2、加鎖的方式 jdk1.7採用segment分段鎖,底層使用的是ReentrantLock。 Jdk1.8採用CAS新增新節點,採用synchronized鎖定連結串列或紅黑二叉樹的首節點。

29、執行緒池的核心引數?

corePoolSize 核心執行緒數目

maximumPoolSize 最大執行緒數目

keepAliveTime 生存時間

unit 時間單位

workQueue

threadFactory 執行緒工廠

handler 拒絕策略

30、拒絕策略有哪些?

1、AbortPolicy:直接丟擲異常,預設策略。

2、CallerRunsPolicy:用呼叫者所在的執行緒來執行任務。

3、DiscardOldestPolicy:丟棄阻塞佇列中最靠前的任務,並執行當前任務。

4、DiscardPolicy:直接丟棄任務。

31、bean的生命週期?

首先會透過一個非常重要的類,叫做BeanDefinition獲取bean的定義資訊,這裡面就封裝了bean的所有資訊,比如,類的全路徑、是否是延遲載入、是否是單例等等這些資訊。

(1)在建立bean的時候,第一步,呼叫建構函式例項化bean

(2)第二步,bean的依賴注入,比如一些set方法的注入、@Autowried自動注入等

(3)第三步,處理Aware介面,如果某一個bean實現了Aware介面,就會重寫方法執行

(4)第四步,初始化前,執行bean的前置處理器,處理@PostConstrut註解

(5)第五步,初始化時,處理InitializingBean介面

(6)第六步,初始化後,執行bean的後置處理器,主要是對bean進行增強

(7)第七步,銷燬bean。

32、MySQL的最左匹配原則?

最左匹配原則就是指在聯合索引中,如果我們的 SQL 語句中用到了聯合索引中的最左邊的索引,那麼這條 SQL 語句就可以利用這個聯合索引去進行匹配。

33、索引失效的情況?

(1)<>不等於會導致索引失效。

(2)模糊查詢中,使用like關鍵字,like查詢以%開頭就會失效,以%結尾不會失效;

(3)不符合最左匹配原則,索引的最左邊那個條件必須有;

(4)索引列進行了型別轉換;

(5)where後使用or導致索引失效;

(6)對索引列進行了計算或使用了函式;

(7)如果使用了複合索引,查詢中包含範圍條件,右側的條件索引也會失效。

34、left join、right join和union join的區別?

(1)join(Inner Join)內連線 取兩表的公共資料(交集)

(2) left Join左連線 返回左表所有的行,右表返回匹配行,不匹配的返回NULL

(3)right Join右連線 返回右表所有的行,左表返回匹配行,不匹配的返回NULL

(4)union 對兩個結果集進行並集操作,重複資料只顯示一次

(5)union All 對兩個結果集進行並集操作,重複資料全部顯示

35、springBoot的事務管理?

事務是指一組操作,這些操作要麼全部成功,要麼全部失敗。如果在一組操作中有一個操作失敗了,那麼整個事務都應該回滾,即撤銷已經執行的操作,從而保證資料的一致性和完整性。

在 Spring Boot 中,我們可以使用事務管理器來管理事務。事務管理器可以確保一系列操作要麼全部成功,要麼全部失敗,從而保證資料的一致性和完整性。Spring Boot 中的事務管理器是透過 AOP 實現的,它可以攔截帶有 @Transactional 註解的方法,並在方法執行前後自動開啟和提交事務。如果方法執行過程中發生異常,事務管理器會自動回滾事務,從而保證資料的一致性和完整性。

如果需要自定義事務管理器,我們可以使用 @Bean 註解在配置類中定義一個事務管理器。

36、執行緒池的執行流程?

首先判斷核心執行緒是否已滿,如果沒有滿則建立核心執行緒執行,如果已經滿了就判斷任務佇列是都已滿,如果沒有滿則將任務放入到任務佇列中,如果滿了就判斷最大執行緒數是否到達,如果沒有到達則建立臨時執行緒執行,如果已經達到則根據拒絕策略處理任務。最後,如果核心或臨時執行緒執行完成任務後會檢查任務佇列中是否有需要執行的執行緒,如果有,則使用非核心執行緒執行任務。

37、對volatile關鍵字的理解?

volatile關鍵字詳解:是Java語言提供的一種稍弱的同步機制,用來確保將變數的更新操作通知到其他執行緒。

-- 當把變數宣告為volatile型別後,編譯時與執行時都會注意到這個變數是共享的,因此不會將該變數上的操作與其他記憶體操作一起重排序。

-- volatile變數不會被快取在暫存器或者對其他處理器不可見的地方,因此在讀取volatile型別的變數時總會返回最新寫入的值。

-- 在訪問volatile變數時不會執行加鎖操作,因此也就不會使執行執行緒阻塞,因此volatile變數是一種比sychronized關鍵字更輕量級的同步機制。

38、如何理解Java併發中的可見性?

  • Java併發可見性指的是多執行緒併發訪問共享變數時,對變數的更改能夠被其他執行緒及時感知, 即在一個執行緒修改變數後,其他執行緒能夠立即看到這個變數的修改結果。

  • 在Java中,可以使用volatile關鍵字來保證變數的可見性,對於加了volatile的變數,執行緒在讀取該變數時會直接從記憶體中讀取,再修改該變數時會同時修改CPU快取記憶體和記憶體中的值。

39、Volatile和Synchronized的區別?

(1)作用的位置不同。 synchronized是修飾方法,程式碼塊。volatile是修飾變數。

(2)作用不同。 synchronized,可以保證變數修改的可見性及原子性,可能會造成執行緒的阻塞;synchronized在鎖釋放的時候會將資料寫入主記憶體,保證可見性。 volatile僅能實現變數修改的可見性,但無法保證原子性,不會造成執行緒的阻塞;volatile修飾變數後,每次讀取都是去主記憶體進行讀取,保證可見性。

40、hashcode和equals的問題?

1、對於hashcode方法,會返回一個雜湊值,雜湊值對陣列的長度取餘後會確定一個儲存的下標位置。 不同的雜湊值取餘之後的結果可能是相同的,用equals方法判斷是否為相同的物件,不同則在連結串列中插入。 則有hashCode()與equals()的相關規定: -- 如果兩個物件相等,則hashcode一定也是相同的; -- 兩個物件相等,對兩個物件分別呼叫equals方法都返回true; -- 兩個物件有相同的hashcode值,它們也不一定是相等的;

2、為什麼重寫 equals 方法必須重寫 hashcode 方法 ? 判斷的時候先根據hashcode進行的判斷,相同的情況下再根據equals()方法進行判斷。如果只重寫了equals方法,而不重寫hashcode的方法,會造成hashcode的值不同,而equals()方法判斷出來的結果為true。 而在Java中的一些容器中,不允許有兩個完全相同的物件,插入的時候,如果判斷相同則會進行覆蓋。這時候如果只重寫了equals()的方法,而不重寫hashcode的方法,Object中hashcode是根據物件的儲存地址轉換而形成的一個雜湊值。這時候就有可能因為沒有重寫hashcode方法,造成相同的物件雜湊到不同的位置從而造成物件的不能覆蓋的問題

41、對反射機制的理解?

1、定義:

反射是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取資訊以及動態呼叫物件的方法的功能稱為 Java 語言的反射機制。

2、優缺點:

優點:能夠執行時動態獲取類的例項,提高靈活性;可與動態編譯結合Class.forName('com.mysql.jdbc.Driver.class');,載入MySQL的驅動類。

缺點:使用反射效能較低,需要解析位元組碼,將記憶體中的物件進行解析。其解決方案是:透過setAccessible(true)關閉JDK的安全檢查來提升反射速度;多次建立一個類的例項時,有快取會快很多;ReflflectASM工具類,透過位元組碼生成的方式加快反射速度。

3、如何獲取反射中的Class物件?

①Class.forName(“類的路徑”);當我們知道該類的全路徑名時,就可以使用該方法獲取 Class 類物件。

②類名.class。這種方法只適合在編譯前就知道操作的 Class。

③物件名.getClass()。

④如果是基本型別的包裝類,可以呼叫包裝類的Type屬性來獲得該包裝類的Class物件。

42、JVM的垃圾回收演算法?

(1)標記清除演算法:

標記階段:把垃圾記憶體標記出來;

清除階段:直接將垃圾記憶體回收;

這種演算法是比較簡單的,但是有個很嚴重的問題,就是會產生大量的記憶體碎片。

(2)複製演算法:為了解決標記清除演算法的記憶體碎片問題,複製演算法將記憶體分為大小相等的兩半,每次只使用其中一半。垃圾回收時,將當前這一塊的存活物件全部複製到另一半,然後當前這一半記憶體就可以直接清除。這種演算法沒有記憶體碎片,但是他的問題就在於浪費空間。而且,他的效率跟存活物件的個數有關。

(3)標記壓縮演算法:為了解決複製演算法的缺陷,就提出了標記壓縮演算法。這種演算法在標記階段跟標記清除演算法是一樣的,但是在完成標記之後,不是直接清理垃圾記憶體,而是將存活物件往一端移動,然後將邊界以外的所有記憶體直接清除

43、HotSpot為什麼要分為新生代和老年代?

HotSpot根據物件存活週期的不同將記憶體劃分為幾塊,一般是把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點採用最適當的收集演算法。在新生代中,每次垃圾收集時都發現有大批物件死去,只有少量存活,那就選用複製演算法,只需要付出少量存活物件的複製成本就可以完成收集。而老年代中因為物件存活率高、沒有額外空間對它進行分配擔保,就必須使用“標記—清理”或者“標記—整理”演算法來進行回收。

其中新生代又分為1個Eden區和2個Survivor區,通常稱為From Survivor和To Survivor區。

44、springBoot的AOP和IOC、DI?

1、AOP是面向切面程式設計,在Spring中用於將那些與業務無關,但卻對多個物件產生影響的公共行為和邏輯,抽取公共模組複用,降低耦合,一般可以作為公共日誌儲存、事務處理等。 2、Spring 中的 IoC 的實現機制就是工廠模式加反射機制。

UserService service = new UserService(); //耦合度太高,維護不方便

引入IOC,將建立物件的控制權交給Spring的IOC,以前由程式設計師自己控制物件建立,現在交給Spring的IOC去建立,如果要去使用物件需要透過DI(依賴注入)比如@Autowried自動注入 就可以使用物件。

優點:(1)集中管理物件,方便維護。(2)降低耦合度。

優點:(1)IOC容器支援載入服務時的餓漢式初始化和懶載入。

(2)最小的代價和最小的侵入性使鬆散耦合得以實現。

3、依賴注入(Dependency Injection,DI)是一種設計模式,它透過將物件之間的依賴關係的建立和維護轉移到外部容器中來,以減少物件之間的緊耦合性並提高可重用性。

45、sql最佳化?

(1)表的設計最佳化,資料型別選擇根據需求來。

(2)索引最佳化(索引建立原則)。

(3)sql語句最佳化(不使用select *,避免索引失效,聚合查詢多用union all(union會多一次過濾),表關聯使用inner join,不使用left join,right join)。

(4)採用主從複製,讀寫分離的模式,讓資料庫的寫入,不影響查詢的效率。

(5)分庫分表。

46、索引的建立原則

(1)被頻繁查詢的欄位。

(2)被作為條件查詢的欄位。

(3)頻繁需要排序的欄位。

頻繁需要分組的欄位。

(4)字串型別的欄位使用字首索引代替普通索引。

(5)不為NULL的欄位。

(6)被經常頻繁用於連線的欄位。

(7)儘可能的考慮建立聯合索引而不是單列索引。

(8)限制每張表上的索引數量。

(9)注意避免冗餘索引,冗餘索引指的是索引的功能相同,應該儘量擴充套件已有的索引而不是建立新索引。

(10)刪除長期未使用的索引。MySQL 5.7可以透過sys庫的schema_unused_indexes檢視來查詢哪些索引從未被使用。

47、SpringBoot中常用註解及其底層實現?

(1)@SpringBootApplication註解:這個註解標識了一個SpringBoot工程,它實際上是另外三個註解的組合,這三個註解是:

a. @SpringBootConfiguration:這個註解實際就是一個@Configuration,表示啟動類也是一個配置類;

b. @EnableAutoConfiguration:向Spring容器中匯入了一個Selector,用來載入ClassPath下SpringFactories中所定義的自動配置類,將這些自動載入為配置Bean;

c. @ComponentScan:標識掃描路徑,因為預設是沒有配置實際掃描路徑,所以SpringBoot掃描的路徑是啟動類所在的當前目錄。

(2)@Bean註解:用來定義Bean,類似於XML中的<bean>標籤,Spring在啟動時,會對加了@Bean註解的方法進行解析,將方法的名字做為beanName,並透過執行方法得到bean物件。

(3)@Controller、@Service、@ResponseBody、@Autowired。

48、HTTP狀態碼有哪些?

49、TCP和UDP的區別?

(1)UDP在傳送資料之前不需要先建立連線。而TCP提供面向連線的服務,在傳送資料之前必須先建立連線,資料傳送結束後要釋放連線。

(2)TCP是面向位元組流的,UDP是面向報文的。

(3)TCP首部開銷(20~60位元組)比UDP首部開銷(8位元組)要大。

(4)由於使用TCP進行傳輸的時候多了連線、確認、重傳等機制,所以TCP的傳輸效率要比UDP低很多。

(5)TCP只支援點對點通訊,UDP支援一對一、一對多、多對一、多對多通訊。

(6)遠地主機在收到UDP報文後,不需要給出任何確認,並且不保證資料不丟失,不保證是否順序到達。TCP提供可靠的傳輸服務,TCP在傳遞資料之前,會有三次握手來建立連線,而且在資料傳遞時,有確認、視窗、重傳、擁塞控制機制。透過TCP連線傳輸的資料,無差錯、不丟失、不重複、並且按序到達。

50、Spring的常見註解?

(1)第一類是:宣告Bean。有@Component、@Service、@Controller、@Repository

(2)第二類是:依賴注入相關的。有@Autowired、@Qualifier、@Resourse

(3)第三類是:設定作用域的。有@Scope

(4)第四類是:Spring配置相關的。有@Configuration、@ComponentScan、@Bean

(5)第五類是:跟AOP相關做增強的註解。有@Aspect、@Before、@After、@Around、@Pointcut

51、SpringMVC的常見註解?

(1)@RequestMapping:用於對映請求路徑

(2)@RequestBody:接收http請求的json資料,將json資料轉換為java物件

(3)@RequestParam:指定請求引數的名稱

(4)@PathViriable:從請求路徑中獲取請求引數(/user/{id}),傳遞給方法的形參

(5)@ReponseBody:將Controller方法返回物件轉換為json物件響應給客戶端

(6)@RequestHeader:獲取指定的請求頭資料

(7)@GetMapping:是一個組合註解, 通常用來處理get請求,常用於執行查詢操作。

是@RequestMapping(value="這裡寫的是請求的路徑",method = RequestMethod.GET)的縮寫。

(8)@PostMapping:是一個組合註解, 通常用來處理post請求,常用於執行新增操作。

是@RequestMapping(value="這裡寫的是請求的路徑",method = RequestMethod.POST)的縮寫。

(9)@PutMapping:是一個組合註解,通常用來處理put請求,常用於執行更新操作。

是@RequestMapping(value="這裡寫的是請求的路徑",method = RequestMethod.PUT)的縮寫。

(10)@DeleteMapping:是一個組合註解。通常用來處理delete請求,常用於執行刪除操作。

是@RequestMapping(value="這裡寫的是請求的路徑",method = RequestMethod.DELETE)的縮寫。

52、MyBatis的執行流程?

(1)讀取MyBatis配置檔案:mybatis-config.xml載入執行環境和對映檔案

(2)構造會話工廠SqlSessionFactory,一個專案只需要一個,單例的,一般由Spring進行管理

(3)會話工廠建立SqlSession物件,這裡面就包含了執行SQL語句的所有方法

(4)運算元據庫的介面,Executor執行器,同時負責查詢快取的維護

(5)Executor介面的執行方法中有一個MappedStatement型別的引數,它封裝了對映資訊

(6)輸入引數對映

(7)輸出結果對映

53、作業系統虛擬記憶體的理解?

虛擬記憶體本質上來說它只是邏輯存在的,是一個假想出來的記憶體空間,主要作用是作為程序訪問主存(實體記憶體)的橋樑並簡化記憶體管理。

54、沒有虛擬記憶體有什麼問題?

如果沒有虛擬記憶體的話,程式直接訪問和操作的都是實體記憶體,看似少了一層中介,但多了很多問題。比如:

(1)使用者程式可以訪問任意實體記憶體,可能會不小心操作到系統執行必需的記憶體,進而造成作業系統崩潰,嚴重影響系統的安全。

(2)同時執行多個程式容易崩潰。比如你想同時執行一個微信和一個 QQ 音樂,微信在執行的時候給記憶體地址 1xxx 賦值後,QQ 音樂也同樣給記憶體地址 1xxx 賦值,那麼 QQ 音樂對記憶體的賦值就會覆蓋微信之前所賦的值,這就可能會造成微信這個程式會崩潰。

(3)程式執行過程中使用的所有資料或指令都要載入實體記憶體,根據區域性性原理,其中很大一部分可能都不會用到,白白佔用了寶貴的實體記憶體資源。

55、什麼是虛擬地址和實體地址?

實體地址是真正的實體記憶體中地址,更具體點來說是記憶體地址暫存器中的地址。程式中訪問的記憶體地址不是實體地址,而是虛擬地址 。 也就是說,我們程式設計開發的時候實際就是在和虛擬地址打交道。 作業系統一般透過CPU晶片中的一個重要元件 MMU(Memory Management Unit,記憶體管理單元) 將虛擬地址轉換為實體地址,這個過程被稱為 地址翻譯/地址轉換

56、虛擬地址與實體記憶體地址是如何對映的?

記憶體管理單元MMU將虛擬地址翻譯為實體地址的主要機制有3種:(1)分段機制(2)分頁機制(3)段頁機制。

①分段機制 以段的形式管理/分配實體記憶體。應用程式的虛擬地址空間被分為大小不等的段。

②分頁機制 把主存(實體記憶體)分為連續等長的物理頁,應用程式的虛擬地址空間劃也被分為連續等長的虛擬頁。現代作業系統廣泛採用分頁機制。

③斷頁機制是結合了段式管理和頁式管理的一種記憶體管理機制,把實體記憶體先分成若干段,每個段又繼續分成若干大小相等的頁。

相關文章