面試彙總

面試題彙總



一、數據結構

  1. 二叉樹的遍歷

前序(根、左、右)
中序(左、根、右)
後序(左、右、根)
參考:https://www.cnblogs.com/llguanli/p/7363657.html
2.


二、網絡

  1. HTTP幾種請求類型
methord 描述
GET 請求指定頁面信息,並返回實體主體
HEAD 類似於GET請求,只不過返回的響應中沒有具體的內容,用於獲取報頭
POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。
PUT 從客戶端向服務器傳送的數據取代指定的文檔的內容。(全部取代)
PATCH 從客戶端向服務器傳送的數據取代指定的文檔的內容。(部分取代)
DELETE 請求服務器刪除指定的頁面。
CONNECT HTTP/1.1協議中預留給能夠將連接改爲管道方式的代理服務器。
OPTIONS 允許客戶端查看服務器的性能。
TRACE 回顯服務器收到的請求,主要用於測試或診斷。
  1. 常見響應碼
響應碼 說明 備註
200 OK 請求已成功
201 Created 資源已創建
204 No Content 請求已成功,但無返回內容
304 Not Modified 緩存有效
400 Bad Request 語義有誤,當前請求無法被服務器理解,請求參數錯誤
401 Unauthorized 當前請求需要用戶認證(登錄)
403 Forbidden 用戶已認證(登錄),但權限不足
404 Not Found 請求源未在服務器上被發現
405 Method Not Allowed 請求方法不能被用於請求相應的資源,如使用PUT方法訪問只接受POST方法的API
500 Internal Server Error 服務端內部錯誤
502 Bad Gateway 網關錯誤
504 Gateway Timeout 網關超時
  1. GET、POST區別

根據HTTP協議規定,GET請求用於信息獲取,應該是安全的和冪等的(無副作用),雖然獲取的結果會變化,但請求不會有任何副作用。

領域 GET POST
作用 查詢數據 創建、修改數據
長度限制 HTTP協議中無限制
但由於各個瀏覽器有自己的對於URI的長度限制
因此會有長度限制
無限制
後退、刷新操作 無影響 會重複提交數據
前端哪些解決方案
後端哪些解決方案
請求過程 TCP三次握手,併發送數據
1. 瀏覽器請求TCP連接
2. 服務器響應TCP連接
3. 瀏覽器確認TCP連接,併發送GET請求頭和數據
4. 服務器響應200,OK
TCP三次握手後,發送數據
1. 瀏覽器請求TCP連接
2. 服務器響應TCP連接
3. 瀏覽器確認TCP連接,併發送POST請求頭
4. 服務器返回100 continue響應
5. 瀏覽器發送POST的數據
6. 服務器響應200,OK
緩存 可以緩存 無法緩存
歷史 數據會保留在瀏覽器歷史中 數據不會有歷史
數據類型 ASCII字符 無限制
安全性 差,數據暴露,遺留歷史 數據不顯示,無歷史記錄
  1. 描述一次HTTP請求全過程

(1) URL部分:協議(HTTP\HTTPS)、DNS域名解析過程、資源路徑

DNS解析過程:www.google.com

  1. 瀏覽器檢查自身緩存,域名所對應IP地址
  2. 瀏覽器緩存未命中,檢查操作系統緩存(hosts文件),是否存在域名對應IP地址
  3. hosts文件未命中,請求LDNS(本地域名服務器)查詢域名
  4. LDNS查詢本地域名解析緩存結果,命中則返回
  5. LDNS未命中緩存,繼續向上級DNS服務器查詢,直至查詢返回域名信息

(2) TCP/IP、DNS、HTTP、HTML、渲染


三、操作系統

  1. Linux常用命令

ls、tail -f、less、more、pwd、rm -rf、mv、cp、find、chmod、chown、grep、top、cat、ps -ef|grep tomcat
2.


四、設計模式

  1. 有哪些設計模式

分爲三類
創建型模式:單例、工廠、抽象工廠、建造者模式、原型模式
結構型模式:適配器模式、過濾器模式、橋接模式、組合模式、裝飾器模式、外觀模式、代理模式、享元模式
行爲型模式:責任鏈模式、命令模式、解釋器模式、迭代器模式、觀察者模式、狀態模式、空對象模式、策略模式、模板模式、訪問者模式、反應器模式
2.


五、Java基礎

  1. 鎖的分類
    • 公平鎖、非公平鎖
      公平鎖是指多個線程按照申請鎖的順序來獲取鎖。
      比如:ReentrantLock,默認是非公平鎖,也可以通過構造函數傳入公平模式創建公平的可重入鎖。而Synchronized只是非公平鎖,誰拿到就是誰的,跟申請順序無關。
    • 排他鎖、共享鎖
      排他鎖,也叫互斥鎖、寫鎖是指該鎖一次只能被一個線程所持有,是一種概念。
      共享鎖是指該鎖可被多個線程所持有,是一種概念。
      ReentrantLock是排他鎖,ReadWriteLock,其中讀是共享鎖,寫是排他鎖。讀寫,寫讀 ,寫寫的過程是互斥的。Synchronized只能是排他鎖。
    • 可重入鎖、讀寫鎖
      ReentrantLock,可重入鎖,是排他鎖的一種實現,加鎖後其他線程無法再獲取這個加鎖對象。ReentrantLock是基於AQS實現,AQS的實現基礎即爲CAS。
      讀寫鎖是一種自旋鎖,即不斷重試。比如讀鎖存在,嘗試進行寫鎖時,會不斷重試,直至讀鎖釋放,纔可以獲取到寫鎖。或當在進行寫加鎖時,讀會不斷重試,直至寫鎖釋放。讀與讀之間不會互斥,會共享鎖。
      爲了防止餓死情況,即讀一直存在,寫鎖拿不到,會在寫嘗試加鎖時,禁止後續的讀再拿到共享鎖,而是等待讀鎖釋放,由等待的寫鎖進行操作。適用於讀多寫少的情況。
    • 樂觀鎖、悲觀鎖
      是指看待併發同步的角度。
      樂觀鎖:認爲對於同一個數據的併發操作,一般是不會發生修改的。
      悲觀鎖:認爲對於同一個數據的併發操作,一定會發生修改。
      樂觀鎖的實現方案:CAS算法(compare and swap)、自旋
      悲觀鎖的實現方案:Synchronized、ReentrantLock、數據庫行鎖、表級鎖等
    • 分段鎖
      分段鎖是一種設計,比如ConcurrentHashMap,採用了分段鎖方式實現高效的併發操作。
      ConcurrentHashMap結構設計有16個Segment,Segment結構即爲HashMap,同時繼承了ReentrantLock,從而實現最高支持16個併發操作。
    • 自旋鎖
      一種鎖設計,是指當一個線程在獲取鎖的時候,如果鎖已經被其它線程獲取,那麼該線程將循環等待,然後不斷的判斷鎖是否能夠被成功獲取,直到獲取到鎖纔會退出循環。
      優點:自動重試獲取鎖,不會阻塞,因爲線程一直是active狀態,不斷循環嘗試獲得鎖,因此無需線程上下文切換。
      缺點:可能會導致busy-waiting忙等待,不公平的自旋鎖可能會導致線程飢餓,一直獲取不到鎖。
      實現原理:CAS思想,如果compareAndSwap成功,則嘗試加鎖成功,否則繼續循環。
  2. Synchronized的同步原理

  synchronized關鍵字可以修飾普通方法、靜態方法、代碼塊,主要分爲代碼塊的同步和方法的同步兩種,兩種同步底層原理相同,但是實現方式稍有不同。
底層原理
  Monitor對象,任何同步的訪問必須先獲取monitor對象,才能進行操作,然後再釋放monitor對象。
代碼塊的同步:
  指令控制,monitorenter,monitorexit
monitorenter:
  每個對象有一個監視器鎖(monitor)。當monitor被佔用時就會處於鎖定狀態,線程執行monitorenter指令時嘗試獲取monitor的所有權,過程如下:

  1. 如果monitor的進入數爲0,則該線程進入monitor,然後將進入數設置爲1,該線程即爲monitor的所有者。
  2. 如果線程已經佔有該monitor,只是重新進入,則進入monitor的進入數進行加1。
  3. 如果其他線程已經佔用了monitor,則該線程進入阻塞狀態,直到monitor的進入數爲0,再重新嘗試獲取monitor的所有權。

monitorexit:
  執行monitorexit的線程必須是objectref所對應的monitor的所有者。
  指令執行時,monitor的進入數減1,如果減1後進入數爲0,那線程退出monitor,不再是這個monitor的所有者。其他被這個monitor阻塞的線程可以嘗試去獲取這個 monitor 的所有權。

方法的同步:
  方法的同步分爲普通方法和靜態方法。靜態方法屬於類,因此需要獲取類鎖,每個類只有一個類鎖,因此同步的靜態方法只能獲得鎖後調用,非同步的方法可以隨意調用。每個類可能會實例化爲很多實例,每個實例有一個對象鎖,不同對象之間加鎖不同。
  可以認爲類鎖也是對象鎖,其實類也是一個Class對象,所有靜態的都是走的類這個對象。類鎖和方法鎖之間不衝突,互相無影響。
  方法的同步採用的是ACC_SYNCHRONIZED標記,即標誌此方法爲同步方法。
  當方法調用時,調用指令將會檢查方法的 ACC_SYNCHRONIZED 訪問標誌是否被設置,如果設置了,執行線程將先獲取monitor,獲取成功之後才能執行方法體,方法執行完後再釋放monitor。
  鎖就存在於Java對象頭中。

  1. Java對象頭

  Java對象在內存中保存,由三部分組成:Java對象頭,實例數據,對齊填充字節。
  Java對象頭由三部分組成:Mark Word,指向類的指針,數組長度(只有數組對象纔有)。
以下爲Mark Word關於鎖的狀態。默認無鎖,標誌位爲01。
Mark Word

JVM一般是這樣使用鎖和Mark Word的:

  1. 當沒有被當成鎖時,這就是一個普通的對象,Mark Word記錄對象的HashCode,鎖標誌位是01,是否偏向鎖那一位是0。
  2. 當對象被當做同步鎖並有一個線程A搶到了鎖時,鎖標誌位還是01,但是否偏向鎖那一位改成1,前23bit記錄搶到鎖的線程id,表示進入偏向鎖狀態。當對象被當做同步鎖並有一個線程A搶到了鎖時,鎖標誌位還是01,但是否偏向鎖那一位改成1,前23bit記錄搶到鎖的線程id,表示進入偏向鎖狀態。
  3. 當線程A再次試圖來獲得鎖時,JVM發現同步鎖對象的標誌位是01,是否偏向鎖是1,也就是偏向狀態,Mark Word中記錄的線程id就是線程A自己的id,表示線程A已經獲得了這個偏向鎖,可以執行同步鎖的代碼。
  4. 當線程B試圖獲得這個鎖時,JVM發現同步鎖處於偏向狀態,但是Mark Word中的線程id記錄的不是B,那麼線程B會先用CAS操作試圖獲得鎖,這裏的獲得鎖操作是有可能成功的,因爲線程A一般不會自動釋放偏向鎖。如果搶鎖成功,就把Mark Word裏的線程id改爲線程B的id,代表線程B獲得了這個偏向鎖,可以執行同步鎖代碼。如果搶鎖失敗,則繼續執行步驟5。
  5. 偏向鎖狀態搶鎖失敗,代表當前鎖有一定的競爭,偏向鎖將升級爲輕量級鎖。JVM會在當前線程的線程棧中開闢一塊單獨的空間,裏面保存指向對象鎖Mark Word的指針,同時在對象鎖Mark Word中保存指向這片空間的指針。上述兩個保存操作都是CAS操作,如果保存成功,代表線程搶到了同步鎖,就把Mark Word中的鎖標誌位改成00,可以執行同步鎖代碼。如果保存失敗,表示搶鎖失敗,競爭太激烈,繼續執行步驟6。
  6. 輕量級鎖搶鎖失敗,JVM會使用自旋鎖,自旋鎖不是一個鎖狀態,只是代表不斷的重試,嘗試搶鎖。從JDK1.7開始,自旋鎖默認啓用,自旋次數由JVM決定。如果搶鎖成功則執行同步鎖代碼,如果失敗則繼續執行步驟7。
  7. 自旋鎖重試之後如果搶鎖依然失敗,同步鎖會升級至重量級鎖,鎖標誌位改爲10。在這個狀態下,未搶到鎖的線程都會被阻塞。

以上即爲JVM使用鎖的過程。

  1. Synchronized與ReentrantLock的區別
領域 Synchronized ReentrantLock
條件 只有一個 可以使用condition組合靈活控制
順序 固定非公平鎖 公平鎖、非公平鎖都支持
鎖超時 阻塞等待 可以嘗試加鎖,可以控制等待時間,可以中斷
操作 加鎖 加鎖、finally解鎖
  1. 原子類-Atomic

  比如:AtomicInteger、AtomicLong等。線程安全的類。
AtomicInteger中會調用Unsafe類下的CompareAndSwapInt方法,通過CAS的思想與自旋的方式,實現同步非阻塞的方式。

  1. AQS

  抽象類:AbstractQueuedSynchronizer,抽象的隊列式同步器,定義了一套多線程訪問共享資源的同步器框架,是java.util.concurrent的核心。

  1. CAS

  CAS指令,CPU指令,compare and swap,Unsafe類下的cas操作會在虛擬機中進行特殊處理,處理爲一條指令信息,通過硬件原子操作實現非阻塞同步,通過沖突檢測和操作完成。
  CAS需要三個操作數,分別是內存位置(用V表示),舊的預期值(用A表示)和新值(用B表示)。CAS執行時,當且僅當V符合舊預期值A時,處理器用新值B更新V的值,否則它就不執行。
  CAS+自旋重試,從而實現樂觀鎖式的操作。

  1. Unsafe類

  Unsafe類是java中非常特別的一個類。它名字就叫做“不安全”,提供的操作可以直接讀寫內存、獲得地址偏移值、鎖定或釋放線程。
  通過正常途徑是無法獲得Unsafe實例的,首先它的構造方法是私有的,然後,即使你調用它的getUnsafe方法,也會拋出SecurityException,因爲getUnsafe方法中檢查該CallerClass(調用方)是不是由系統類加載器BootstrapClassLoader加載。除非通過反射機制,才能跳過安全檢查。
功能:

  • 讀功能:讀取內存中的某塊數據
  • 寫功能:
  • CAS操作:compareAndSwapXXX,原子操作,cpu在執行cas時對這一塊內存是獨佔排他的。在併發包中很多操作真正執行的也是cas,併發包中的類併發性能比使用 synchronized 關鍵字好也在於此:鎖的粒度小了許多並且少了線程上下文切換。
  • park、unpark:線程掛起、恢復線程。(比如:ReentrantLock,在線程加鎖失敗時會進行掛起,就是走的park,直至超時或中斷)
  1. 多線程

什麼是進程?什麼是線程?進程與線程的區別?什麼是多線程?多線程解決什麼問題?多線程可能會引入哪些問題?
參考:https://blog.csdn.net/yaosiming2011/article/details/44280797

  1. 死鎖的解決
  2. 同步、異步、阻塞、非阻塞

同步、異步是結果,阻塞、非阻塞是過程。
同步、異步是目的,阻塞、非阻塞是實現方式。
調用同步的方法在沒有拿到鎖的情況下會出現阻塞,在獲得鎖的情況下不會出現阻塞。
BIO:blocking IO,阻塞式IO。

  1. NIO的原理
  2. wait\notify

六、數據庫

  1. 事務-四要素
  • 原子性(Atomicity):事務開始後所有操作,要麼全部做完,要麼全部不做,不可能停滯在中間環節。事務執行過程中出錯,會回滾到事務開始前的狀態,所有的操作就像沒有發生一樣。也就是說事務是一個不可分割的整體,就像化學中學過的原子,是物質構成的基本單位。
  • 一致性(Consistency):事務開始前和結束後,數據庫的完整性約束沒有被破壞 。比如A向B轉賬,不可能A扣了錢,B卻沒收到。
  • 隔離性(Isolation):同一時間,只允許一個事務請求同一數據,不同的事務之間彼此沒有任何干擾。
  • 持久性(Durability):事務完成後,事務對數據庫的所有更新將被保存到數據庫。
  1. 事務隔離級別
  • read-uncommitted,讀未提交,導致
  • read-committed,不可重複讀
  • repeatable-read,可重複讀
  • serializable,串行化
  1. 事務併發問題
  • 髒讀:事務A讀取到事務B還未提交的新數據,但事務B最後執行失敗,回滾了數據,因此事務A讀到了錯誤的髒數據。
  • 不可重複讀:事務A多次讀取同一數據,由於事務B在更新、修改此數據,導致事務A多次讀同一數據出現不同結果。(針對某行記錄的修改)
  • 幻讀:事務A統計某一條件的所有數據信息,事務B剛創建一條符合條件的數據,在事務A根據相同條件再查詢時,發現統計數據又多了一條,好像出現了幻覺。(針對結果集的刪除、新增)
  1. 樂觀鎖、悲觀鎖,及其實現

  鎖是一種方式,並非數據庫獨有。

  1. MVCC

  多版本併發控制機制
  InnoDB的MVCC,是通過在每行記錄後面保存兩個隱藏的列來實現的,分別保存了這個行的創建時間和刪除時間。這裏存儲的並不是實際的時間值,而是系統版本號(可以理解爲自增ID),其實是CAS(compare and swap)的思想。


六、開源框架

  1. RPC框架
  2. MQ框架
  3. MQ消息重複如何處理
  4. MQ如何保證順序,是否可以併發消費順序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章