JVM的記憶體結構
根據 JVM 規範,JVM 記憶體共分為虛拟機棧、堆、方法區、程式計數器、本地方法棧五個部分。
1. Java虛拟機棧:線程私有;每個方法在執行的時候會建立一個棧幀,存儲了局部變量表,操作數棧,動态連接配接,方法傳回位址等;每個方法從調用到執行完畢,對應一個棧幀在虛拟機棧中的入棧和出棧。
2. 堆:線程共享;被所有線程共享的一塊記憶體區域,在虛拟機啟動時建立,用于存放對象執行個體。
3. 方法區:線程共享;被所有線程共享的一塊記憶體區域;用于存儲已被虛拟機加載的類資訊,常量,靜态變量等。
4. 程式計數器:線程私有;是目前線程所執行的位元組碼的行号訓示器,每條線程都要有一個獨立的程式計數器,這類記憶體也稱為“線程私有”的記憶體。
5. 本地方法棧:線程私有;主要為虛拟機使用到的Native方法服務。
為什麼要用線程池
那先要明白什麼是線程池
線程池是指在初始化一個多線程應用程式過程中建立一個線程集合,然後在需要執行新的任務時重用這些線程而不是建立一個線程。
使用線程池的好處
- 線程池改進了一個應用程式的響應時間。由于線程池中的線程已經準備好且等待被配置設定任務,應用程式可以直接拿來使用而不用建立一個線程。
- 線程池節省了CLR 為每個短生存周期任務建立一個完整的線程的開銷并可以在任務完成後回收資源。
- 線程池根據目前在系統中運作的程序來優化線程時間片。
- 線程池允許我們開啟多個任務而不用為每個線程設定屬性。
- 線程池允許我們為正在執行的任務的程式參數傳遞一個包含狀态資訊的對象引用。
- 線程池可以用來解決處理一個特定請求最大線程數量限制問題。
MySQL優化經驗
- 對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
- 應盡量避免在 where 子句中使用!=或<>操作符,否則引擎将放棄使用索引而進行全表掃描。
- 盡量使用數字型字段,若隻含數值資訊的字段盡量不要設計為字元型,這會降低查詢和連接配接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接配接時會逐個比較字元串中每一個字元,而對于數字型而言隻需要比較一次就夠了。
- 任何地方都不要使用 select from t ,用具體的字段清單代替“”,不要傳回用不到的任何字段。
- 避免頻繁建立和删除臨時表,以減少系統表資源的消耗。諸如此類,等等等等......
什麼是線程死鎖?死鎖如何産生?如何避免線程死鎖?
死鎖的介紹:
線程死鎖是指由于兩個或者多個線程互相持有對方所需要的資源,導緻這些線程處于等待狀态,無法前往執行。當線程進入對象的synchronized代碼塊時,便占有了資源,直到它退出該代碼塊或者調用wait方法,才釋放資源,在此期間,其他線程将不能進入該代碼塊。當線程互相持有對方所需要的資源時,會互相等待對方釋放資源,如果線程都不主動釋放所占有的資源,将産生死鎖。
死鎖的産生的一些特定條件:
- 互斥條件:程序對于所配置設定到的資源具有排它性,即一個資源隻能被一個程序占用,直到被該程序釋放 。
- 請求和保持條件:一個程序因請求被占用資源而發生阻塞時,對已獲得的資源保持不放。
- 不剝奪條件:任何一個資源在沒被該程序釋放之前,任何其他程序都無法對他剝奪占用。
- 循環等待條件:當發生死鎖時,所等待的程序必定會形成一個環路(類似于死循環),造成永久阻塞。
如何避免:
1. 加鎖順序:當多個線程需要相同的一些鎖,但是按照不同的順序加鎖,死鎖就很容易發生。如果能確定所有的線程都是按照相同的順序獲得鎖,那麼死鎖就不會發生。當然這種方式需要你事先知道所有可能會用到的鎖,然而總有些時候是無法預知的。
2. 加鎖時限:加上一個逾時時間,若一個線程沒有在給定的時限内成功獲得所有需要的鎖,則會進行回退并釋放所有已經獲得的鎖,然後等待一段随機的時間再重試。但是如果有非常多的線程同一時間去競争同一批資源,就算有逾時和回退機制,還是可能會導緻這些線程重複地嘗試但卻始終得不到鎖。
3. 死鎖檢測:死鎖檢測即每當一個線程獲得了鎖,會線上程和鎖相關的資料結構中(map、graph等等)将其記下。除此之外,每當有線程請求鎖,也需要記錄在這個資料結構中。死鎖檢測是一個更好的死鎖預防機制,它主要是針對那些不可能實作按序加鎖并且鎖逾時也不可行的場景。
spring中Bean的作用域
1. singleton:Spring IoC容器中隻會存在一個共享的Bean執行個體,無論有多少個Bean引用它,始終指向同一對象。Singleton作用域是Spring中的預設作用域。
2. prototype:每次通過Spring容器擷取prototype定義的bean時,容器都将建立一個新的Bean執行個體,每個Bean執行個體都有自己的屬性和狀态,而singleton全局隻有一個對象。
3. request:在一次Http請求中,容器會傳回該Bean的同一執行個體。而對不同的Http請求則會産生新的Bean,而且該bean僅在目前Http Request内有效。
4. session:在一次Http Session中,容器會傳回該Bean的同一執行個體。而對不同的Session請求則會建立新的執行個體,該bean執行個體僅在目前Session内有效。
5. global Session:在一個全局的Http Session中,容器會傳回該Bean的同一個執行個體,僅在使用portlet context時有效。
Spring架構中都用到了哪些設計模式?
1. 代理模式:在AOP和remoting中被用的比較多。
2. 單例模式:在spring配置檔案中定義的bean預設為單例模式。
3. 模闆方法模式:用來解決代碼重複的問題。
4. 前端控制器模式:Spring提供了DispatcherServlet來對請求進行分發。
5. 依賴注入模式:貫穿于BeanFactory / ApplicationContext接口的核心理念。
6. 工廠模式:BeanFactory用來建立對象的執行個體。
springmvc的核心是什麼,請求的流程是怎麼處理的,控制反轉怎麼實作的
核心:控制反轉和面向切面
請求處理流程:
- 首先使用者發送請求到前端控制器,前端控制器根據請求資訊(如URL)來決定選擇哪一個頁面控制器進行處理并把請求委托給它,即以前的控制器的控制邏輯部分;
- 頁面控制器接收到請求後,進行功能處理,首先需要收集和綁定請求參數到一個對象,并進行驗證,然後将指令對象委托給業務對象進行處理;處理完畢後傳回一個ModelAndView(模型資料和邏輯視圖名);
- 前端控制器收回控制權,然後根據傳回的邏輯視圖名,選擇相應的視圖進行渲染,并把模型資料傳入以便視圖渲染;
- 前端控制器再次收回控制權,将響應傳回給使用者。
控制反轉如何實作:
- 我們每次使用spring架構都要配置xml檔案,這個xml配置了bean的id和class。
- spring中預設的bean為單執行個體模式,通過bean的class引用反射機制可以建立這個執行個體。
- 是以,spring架構通過反射替我們建立好了執行個體并且替我們維護他們。
- A需要引用B類,spring架構就會通過xml把B執行個體的引用傳給了A的成員變量。
BAT大廠Java進階面試題常見30問
- Spring DAO 中最常用的類是什麼?
- 如何在Spring應用中使用SLF4J?
- Spring bean 的預設作用範圍是?
- 使用@Required但不關聯bean 來注解setter方法,将會發生?
- 已知一棵二叉樹前序周遊和中序周遊分别為ABDEGCFH和DBGEACHF,則該二叉樹的後序周遊為?
- volatile關鍵字是否能保證線程安全?
- Java能不能不通過構造函數建立對象?
- Java程式的并發機制是?
- 方法resume()負責恢複哪些線程的執行?
- 什麼是LinkedHashSet?
- 什麼是可變參數?
- 斷言的用途?
- 什麼時候使用斷言?
- 什麼是垃圾回收?
- 用一個例子解釋垃圾回收?
- 什麼時候運作垃圾回收?
- 垃圾回收的最佳做法?
- 什麼是初始化資料塊?
- 什麼是靜态初始化器?
- 什麼是執行個體初始化塊?
- 什麼是正規表達式?
- 什麼是令牌化?
- 給出令牌化的例子?
- 如何使用掃描器類(Scanner Class)令牌化?
- 如何添加小時(hour)到一個日期對象(Date Objects)?
- 如何格式化日期對象?
- Java中月曆類(Calendar Class)的用途?
- 如何在Java中擷取月曆類的執行個體?
- 解釋一些月曆類中的重要方法?
- 數字格式化類(Number Format Class)的用途?
讀者福利
由于篇幅有限,部分答案就不做全部展示了,這些面試題的答案我已經整理成PDF文檔了,同時也整理了一些問題詳解;雖然說花了一點時間,但是我也願意把它免費分享出來,希望能夠幫助到有需要的Java工程師朋友,也省的大家再去網上花時間找資料。
領取方式:公衆号背景回複【面試】,即可免費領取!