各位在面試時,必然會遇到各位的技術問題。這次針對Java后端開發,以下這篇文章羅列了各大公司技術面試官可能會提及的問題,并做出了解答。若覺得不錯,希望分享給更多求職的小伙伴哦~
問題一
實現內存共享,為每個線程維護一個本地變量。
采用空間換時間,它用于線程間的數據隔離,為每一個使用該變量的線程提供一個副本,每個線程都可以獨立地改變自己的副本,而不會和其他線程的副本沖突。
類中維護一個Map,用于存儲每一個線程的變量副本,Map中元素的鍵為線程對象,而值為對應線程的變量副本。
在中發揮著巨大的作用c 應用程序初始化失敗,在管理作用域中的Bean、事務管理、任務調度、AOP等模塊都出現了它的身影。
中絕大部分Bean都可以聲明成作用域,采用進行封裝,因此有狀態的Bean就能夠以的方式在多線程中正常工作了。
問題二
Java內存模型
程序計數器:是一個數據結構,用于保存當前正常執行的程序的內存地址。Java虛擬機的多線程就是通過線程輪流切換并分配處理器時間來實現的,為了線程切換后能恢復到正確的位置,每條線程都需要一個獨立的程序計數器,互不影響,該區域為“線程私有”。
Java虛擬機棧:線程私有的,與線程生命周期相同,用于存儲局部變量表,操作棧,方法返回值。局部變量表放著基本數據類型,還有對象的引用。
本地方法棧:跟虛擬機棧很像,不過它是為虛擬機使用到的方法服務。
Java堆:所有線程共享的一塊內存區域,對象實例幾乎都在這分配內存。
方法區:各個線程共享的區域,儲存虛擬機加載的類信息,常量,靜態變量,編譯后的代碼。
運行時常量池:代表運行時每個class文件中的常量表。包括幾種常量:編譯時的數字常量、方法或者域的引用。
問題三
java GC是在什么時候
對什么東西
做了什么事情?
新生代有一個Eden區和兩個區,首先將對象放入Eden區,如果空間不足就向其中的一個區上放,如果仍然放不下就會引發一次發生在新生代的minor GC,將存活的對象放入另一個區中,然后清空Eden和之前的那個區的內存。在某次GC過程中,如果發現仍然又放不下的對象,就將這些對象放入老年代內存里去。
大對象以及長期存活的對象直接進入老年區。
當每次執行minor GC的時候應該對要晉升到老年代的對象進行分析,如果這些馬上要到老年區的老年對象的大小超過了老年區的剩余大小,那么執行一次Full GC以盡可能地獲得老年區的空間。
新生代:復制清理;
老年代:標記-清除和標記-壓縮算法;
永久代:存放Java中的類和加載類的類加載器本身。
虛擬機棧中的引用的對象
方法區中靜態屬性引用的對象,常量引用的對象
本地方法棧中JNI(即一般說的方法)引用的對象。
問題四
與Lock都是可重入鎖,同一個線程再次進入同步代碼的時候.可以使用自己已經獲取到的鎖。
是悲觀鎖機制,獨占鎖。而Locks.是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。
某個線程在等待一個鎖的控制權的這段時間需要中斷
需要分開處理一些wait-,里面的應用,能夠控制哪個線程,鎖可以綁定多個條件。
具有公平鎖功能,每個到來的線程都將排隊等候。
問題五
是線程安全的,每次操作字符串,會生成一個新的對象,而不會;是非線程安全的
問題六
機制是java集合()中的一種錯誤機制。當多個線程對同一個集合的內容進行操作時,就可能會產生fail-fast事件。
例如:當某一個線程A通過去遍歷某集合的過程中,若該集合的內容被其他線程所改變了;那么線程A訪問集合時,就會拋出異常,產生fail-fast事件
問題七
-:如果兩個操作之間具有- 關系,那么前一個操作的結果就會對后面一個操作可見。
程序順序規則:一個線程中的每個操作,- 于該線程中的任意后續操作。
監視器鎖規則:對一個監視器鎖的解鎖,- 于隨后對這個監視器鎖的加鎖。
變量規則:對一個域的寫,- 于任意后續對這個域的讀。
傳遞性:如果A - B,且B - C,那么A - C。
線程啟動規則:對象的start()方法- 于此線程的每一個動作。
問題八
粒度不同,前者針對變量 ,后者鎖對象和類
syn阻塞,線程不阻塞
syn保證三大特性,不保證原子性
syn編譯器優化,不優化 具備兩種特性:
保證此變量對所有線程的可見性,指一條線程修改了這個變量的值,新值對于其他線程來說是可見的,但并不是多線程安全的。
禁止指令重排序優化。
當寫一個變量時,JMM會把該線程對應的本地內存中的共享變量刷新到主內存。
當讀一個變量時,JMM會把該線程對應的本地內存置為無效。線程接下來將從主內存中讀取共享變量。
問題九
CAS是樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改為B,否則什么都不做。
問題十
在程序啟動的時候就創建若干線程來響應處理,它們被稱為線程池,里面的線程叫工作線程
降低資源消耗。通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。
提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。
提高線程的可管理性。
是主要的實現類,其中常用的有 .(),(),(),ol()。
問題十一
裝載:將Java二進制代碼導入jvm中,生成Class文件。
連接:
a)校驗:檢查載入Class文件數據的正確性
b)準備:給類的靜態變量分配存儲空間
c)解析:將符號引用轉成直接引用
初始化:對類的靜態變量,靜態方法和靜態代碼塊執行初始化工作。
問題十二
緩存:
數據結構:key,value對
使用方法:get,put等方法
問題十三
—字符串(key-value 類型)
Hash—字典() Redis的哈希結構可以使你像在數據庫中更新一個屬性一樣只修改某一項屬性值
List—列表 實現消息隊列
Set—集合 利用唯一性
Set—有序集合 可以進行排序 可以實現數據持久化
問題十四
B+,B-,全文索引
Mysql的索引是一個數據結構,旨在使數據庫高效的查找數據。
常用的數據結構是B+Tree,每個葉子節點不但存放了索引鍵的相關信息還增加了指向相鄰葉子節點的指針,這樣就形成了帶有順序訪問指針的B+Tree,做這個優化的目的是提高不同區間訪問的性能。
經常出現在group by,order by和關鍵字后面的字段
經常與其他表進行連接的表,在連接字段上應該建立索引
經常出現在Where子句中的字段
經常出現用作查詢選擇的字段
問題十五
支持三種依賴注入方式,分別是屬性(方法)注入,構造注入和接口注入。
在中,那些組成應用的主體及由 IOC容器所管理的對象被稱之為Bean。
的IOC容器通過反射的機制實例化Bean并建立Bean之間的依賴關系。
簡單地講,Bean就是由 IOC容器初始化、裝配及被管理的對象。
獲取Bean對象的過程,首先通過加載配置文件并啟動IOC容器,然后通過方法獲取bean對象,就可以調用他的方法。
: IOC容器中只有一個共享的Bean實例c 應用程序初始化失敗,一般都是作用域。
:每一個請求,會產生一個新的Bean實例。
:每一次http請求會產生一個新的Bean實例。
問題十六
業務類只需要關注業務邏輯本身,保證了業務類的重用性。
代理對象和目標對象實現了相同的接口,目標對象作為代理對象的一個屬性,具體接口實現中,代理對象可以在調用目標對象相應方法前后加上其他業務處理邏輯。
缺點:一個代理類只能代理一個業務類。如果業務類增加方法時,相應的代理類也要增加方法。
Java動態代理是寫一個類實現接口,重寫方法,在方法可以進行增強處理的邏輯的編寫,這個公共代理類在運行的時候才能明確自己要代理的對象,同時可以實現該被代理類的方法的實現,然后在實現類方法的時候可以進行增強處理。
實際上:代理對象的方法 = 增強處理 + 被代理對象的方法
JDK動態代理只能針對實現了接口的類生成代理(實例化一個類)。此時代理對象和目標對象實現了相同的接口,目標對象作為代理對象的一個屬性,具體接口實現中,可以在調用目標對象相應方法前后加上其他業務處理邏輯
CGLIB是針對類實現代理,主要是對指定的類生成一個子類(沒有實例化一個類),覆蓋其中的方法 。
性能檢測,訪問控制,日志管理,事務等。
默認的策略是如果目標類實現接口,則使用JDK動態代理技術,如果目標對象沒有實現接口,則默認會采用CGLIB代理
問題十七
客戶端請求提交到
由控制器查詢,找到并分發到指定的中。
調用業務邏輯處理后,返回
查詢一個或多個視圖解析器,找到指定的視圖
視圖負責將結果顯示到客戶端
問題十八
DNS域名解析 –> 發起TCP的三次握手 –> 建立TCP連接后發起http請求 –> 服務器響應http請求,瀏覽器得到html代碼 –> 瀏覽器解析html代碼,并請求html代碼中的資源(如、css、圖片等) –> 瀏覽器對頁面進行渲染呈現給用戶
設計一個叫“中間層”的一個邏輯層,在這個層,將數據庫的海量數據抓出來,做成緩存,運行在服務器的內存中,同理,當有新的數據到來,也先做成緩存,再想辦法,持久化到數據庫中,這是一個簡單的思路。主要的步驟是負載均衡,將不同用戶的請求分發到不同的處理節點上,然后先存入緩存,定時向主數據庫更新數據。讀寫的過程采用類似樂觀鎖的機制,可以一直讀(在寫數據的時候也可以),但是每次讀的時候會有個版本的標記,如果本次讀的版本低于緩存的版本,會重新讀數據,這樣的情況并不多,可以忍受。
問題十九
可以讓服務端跟蹤每個客戶端的訪問,但是每次客戶端的訪問都必須傳回這些,如果很多,則無形的增加了客戶端與服務端的數據傳輸量。
而則很好地解決了這個問題,同一個客戶端每次和服務端交互時,將數據存儲通過到服務端,不需要每次都傳回所有的值,而是傳回一個ID,每個客戶端第一次訪問服務器生成的唯一的ID,客戶端只要傳回這個ID就行了,這個ID通常為NAME為的一個。這樣服務端就可以通過這個ID,來將存儲到服務端的KV值取出了。
和的超時問題,的安全問題
問題二十
配置服務器,集群管理服務器可以統一管理所有服務器的配置文件
共享這些存儲在一個分布式緩存中,可以隨時寫入和讀取,而且性能要很好,如,Tair。