1. 程式人生 > >各大公司後端開發面試題總結

各大公司後端開發面試題總結

2、Java記憶體模型:
Java虛擬機器規範中將Java執行時資料分為六種。
1.程式計數器:是一個數據結構,用於儲存當前正常執行的程式的記憶體地址。Java虛擬機器的多執行緒就是通過執行緒輪流切換並分配處理器時間來實現的,為了執行緒切換後能回覆到正確的位置,每條執行緒都需要一個獨立的程式計數器,互不影響,該區域為“執行緒私有”。
2.Java虛擬機器棧:執行緒私有的,與執行緒生命週期相同,用於儲存區域性變量表,操作棧,方法返回值。區域性變量表存放著基本資料型別,還有物件的應用。
3.本地方法棧:跟虛擬機器棧很像,不過它是為虛擬機器使用到的Native方法服務。
4.Java堆:所有執行緒共享的一塊記憶體區域,物件例項幾乎都在這分配記憶體。
5.方法區:各個執行緒共享的區域,儲存虛擬機器載入的類資訊,常量,靜態變數,編譯後的程式碼。
6.執行時常量池:代表執行時每個class檔案中的常量表。包括幾種常量:編譯時的數字常量、方法或者域的引用。
友情連結:Java中JVM虛擬機器詳解
3、“你能不能談談,java GC是在什麼時候,對什麼東西,做了什麼事情?”
在什麼時候:
1.新生代有一個Eden區和兩個survivor區,首先將物件放入Eden區,如果空間不足就向其中的一個survivor區上放,如果仍然放不下就會引發一個發生在新生代的minor GC,將存活的物件放入另一個survivor區中,然後清空Eden和之前的那個survivor區的記憶體。在某次GC過程中,如果發現仍然有放不下的物件,就將這些物件放入老年代記憶體裡去。
2.大物件以及長期存活的物件直接進入老年區。
3.當每次執行minor GC的時候應該對要晉升到老年代的物件進行分析,如果這些馬上要到老年代的老年物件的大小超過了老年區的剩餘大小,那麼執行一個Full GC以儘可能的獲得老年區的空間。
對什麼東西:從GC Roots搜尋不到,而且經過一次標記清理之後仍沒有復活的物件。
做什麼:新生代:複製清理;老年代:標記-清除和標記-壓縮演算法;永久代:存放Java中的類和載入類的類載入器本身。
GC Roots都有哪些:1.虛擬機器棧中的引用的物件 2.方法區中靜態屬性引用的物件,常量引用的物件 3.本地方法棧中JNI(即一般說的Native方法)引用的物件。
4、Synchronized
與Lock都是可重入鎖,同一個執行緒再次進入同步程式碼的時候,可以使用自己已經獲取到的鎖。
Synchroized是悲觀鎖機制,獨佔鎖。而Locks.ReentrantLock是,每次不加鎖而是假設沒有衝突而去完成某項操作,如果因為衝突失敗就重試,直到成功為止。ReentrantLock適用場景
某個執行緒在等待一個鎖的控制權的這段時間需要中斷
需要分開處理一些wait-notify,ReentrantLock裡面的Condition應用,能夠控制notify哪個執行緒,鎖可以繫結多個條件。
具有公平鎖功能,每個到來的執行緒都將排隊等候。
happens-before
如果兩個操作之間具有happens-before關係,那麼前一個操作的結果就會對後面一個操作可見。
1.程式順序規則:一個執行緒中的每個操作,happens-before於該執行緒中的任意後續操作。
2.監視器鎖規則:對一個監視器鎖的解鎖,happens-before於隨後對這個監視器鎖的加鎖。
3.volatile變數規則:對一個volatile域的寫,happens-before與任意後續對這個volatile域的讀。
4.傳遞性:如果A happens-before B,且B happens-before C,那麼A happens-before C。
5.執行緒啟動規則:Thread物件的start()方法happens-before於此執行緒的每一個動作。
Volatile和Synchronized四個不同點:
1 粒度不同,前者針對變數,後者鎖物件和類
2 syn阻塞,volatile執行緒不阻塞
3 syn保證三大特性,volatile不保證原子性
4 syn編譯器優化,volatile不優化,volatile具備兩種特性:
1.保證此變數對所有執行緒的可見性,指一條執行緒修改了這個變數的值,新值對於其他執行緒來說是可見的,但並不是多執行緒安全的。
2.禁止指令重排序優化。
Volatile如何保證記憶體可見性
1.當寫一個volatile變數時,JVM會把該執行緒對應的本地記憶體中的共享變數重新整理到朱記憶體。
2.當讀一個volatile變數時,JVM會把該執行緒對應的本地記憶體置為無效。執行緒接下來將從主記憶體中讀取共享變數。
同步:
就是一個任務的完成需要依賴另外一個任務,只有等待被依賴的任務完成後,依賴任務才能完成
非同步:
不需要等待被依賴的任務完成,只是通知被依賴的任務要完成什麼工作,只要自己任務完成了就算完成了,被依賴的任務是否完成會通知回來。(非同步的特點就是通知)。打電話和發簡訊來比喻同步和非同步操作。
阻塞:
CPU停下來等一個慢的操作完成以後,才會接著完成其他的工作。
非阻塞:
非阻塞就是在這個慢的執行時,CPU去做其他工作,等這個慢的完成後,CPU才會接著完成後續的操作。
非阻塞會造成執行緒切換增加,增加CPU的使用時間能不能補償系統的切換成本需要考慮。
CAS(Compare And Swap)無鎖演算法:
CAS是樂觀鎖技術,當多個執行緒嘗試使用CAS同時更新同一個變數時,只有其中一個執行緒能更新變數的值,而其它執行緒都失敗,失敗的執行緒並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試。CAS有三個運算元,記憶體值V,舊的預期值A,要修改的新值B。當且僅當預期值A和記憶體值V相同時,將記憶體值修改為B,否則什麼都不做。
執行緒池的作用:
在程式啟動的時候就建立若干執行緒來響應處理,他們被稱為執行緒池,裡面的執行緒叫工作執行緒
第一:降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。
第二:提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。
第三:提高執行緒的可管理性。
常用執行緒池:ExecutorService是主要的實現類,其中常用的有Executors.newSingleThreadPool(),newFixedThreadPool(),newcacheThreadPool(),newScheduledThreadPool()。
類載入器工作機制:
1.裝載:將Java二進位制程式碼匯入jvm中,生成Class檔案。
2.連線:a)校驗:檢查載入Class檔案資料的正確性b)準備:給類的靜態變數分配儲存空間c)將符號引用轉成直接引用
3:初始化:對類的靜態變數,靜態方法和靜態程式碼塊執行初始化工作。
雙親委派模型:類載入器收到類載入請求,首先將請求委派給父類載入器完成 使用者自定義載入器->應用程式載入器->擴充套件類載入器->啟動類載入器。
Redis資料結構:
String–字串(key-value型別)
Hash–字典(hashmap)Redis的雜湊結構可以使你像在資料庫中更新一個屬性一樣只修改某一項屬性值
List–列表 實現訊息佇列
Set–集合 利用唯一性
Sorted Set–有序集合 可以進行排序 可以實現資料持久化
B+,B-,全文索引
Mysql的索引是一個數據結構,旨在使資料庫高效的查詢資料。
常用的資料結構是B+Tree,每個葉子節點不但存放了索引鍵的相關資訊還增加了指向相鄰葉子節點的指標,這樣就形成了帶有順序訪問指標的B+Tree,做這個優化的目的是提高不同區間訪問的效能。
什麼時候使用索引:
經常出現在groupby,orderby和distinc關鍵字後面的欄位
經常與其他表進行連線的表,在連線欄位上應該建立索引
經常出現在Where字句中的欄位
經常出現用作查詢的欄位
Spring AOP應用場景
效能檢測,訪問控制,日誌管理,事務等。
預設的策略是如果目標類實現介面,則使用JDK動態代理技術,如果目標物件沒有實現介面,則預設會採用CGLIB代理
分散式Session框架
配置伺服器,Zookeeper叢集管理伺服器可以統一管理所有伺服器的配置檔案
共享這些Session儲存在一個分散式快取中,可以隨時寫入和讀取,而且效能要很好,如Memcache,Tair。
封裝一個類繼承自HttpSession,將Session存入到這個類中然後再存入分散式快取中
由於Cookie不能跨越訪問,要實現Session同步,要同步SessionID寫到不同域名下。
介面卡模式:
將一個介面適配到另一個介面,Java I/O中InputStreamReader將Reader適配到InputStream,從而實現了位元組流到字元流的轉換。
裝飾者模式
保持原來的介面,增強原來有的功能
FileInputStream實現了InputStream的所有介面,BufferdInputStreams繼承自FileInputStream是具體的裝飾器實現者,將InputStream讀取的內容儲存在記憶體中,而提高讀取的效能。
Spring事務配置方法:
1.切點資訊,用於定位實施事務切面的業務類方法
2.控制事務行為的事務屬性,這些屬性包括事務隔離級別,事務傳播行為,超時時間,回滾規則
Spring通過aop/tx Schema名稱空間和@Transaction註解技術來進行宣告式事務配置。
Mybatis
每一個Mybatis的應用程式都以一個SqlSessionFactory物件的例項為核心。首先用位元組流通過Resource將配置檔案讀入,然後通過SqlSessionFactoryBuilder().build方法