一些出的不錯的Java面試題(二)

知道時序數據庫嗎?

時序數據庫是用於存放時序數據的數據庫,而時序數據指基於時間的一系列數據,能夠揭示數據的趨勢性和規律性,對於大數據分析有重要的意義mysql

時序數據庫支持快速寫入、持久化,以及多維度的聚合查詢等,相比傳統的數據庫,時序數據庫記錄了全部的歷史數據,在查詢上也會帶上時間做爲過濾條件redis

mysql的各類加鎖機制簡單講一下

  • 共享鎖和排它鎖:共享鎖和排它鎖至關於讀鎖和寫鎖
  • 意向鎖:表級鎖,表示稍後對錶中的行須要使用的鎖類型
  • 記錄鎖:索引記錄上的鎖
  • 間隙鎖:鎖定索引記錄的間隙,該範圍內的全部值都會被鎖定
  • 後鍵鎖:記錄鎖和間隙鎖的組合,是索引記錄鎖加上該索引記錄前一個間隙的間隙鎖
  • 插入意向鎖:一種特殊的間隙鎖,能夠避免插入到相同索引間隙中的不一樣位置的事務進行等待
  • 自增鎖:插入具備自增屬性的列使用的特殊表級鎖
  • 空間索引的謂詞鎖:支持包含SPATIAL索引的表的隔離級別

JDK8默認的垃圾收集器是什麼

Parallel Scavenge + Serial Oldsql

Redis的數據結構底層是如何實現的?

  • string:定義了SDS數據結構用於實現字符串,重寫了大量字符串處理的模板方法
  • list:結合了雙向鏈表ziplist壓縮列表,在查詢和修改的效率上達到了平衡
  • hash:有zipmap和dict兩種實現方式,zipmap基於列表,dict基於鏈表
  • set:基於柔性數組[1]實現,若是集合過大,會使用dict進行存儲
  • zset:有兩種實現方式,一種是使用zipmap將數據按照值順序存儲,一種是基於跳躍表存儲

Spring建立Bean有哪三種方式?

  • 默認無參方式:將類交給Spring的BeanFactory管理
  • 靜態工廠:把建立實例的方法交給Spring管理。若是第三方依賴中沒有暴露類的構造方法,只提供靜態工廠的方法時,可使用這種方式將類交給Spring管理
  • 實例工廠方式:把工廠類交給Spring管理

i++和++i在JVM層面的實現有什麼區別?

i++的JVM彙編指令[2]iload => iinc => istore,執行順序爲:數據庫

  1. 把i加載到操做數棧
  2. i自增1
  3. 把棧頂的值存儲到指定變量的位置

++i的JVM彙編指令是iinc => iload => istore,執行順序爲:數組

  1. i自增1
  2. 把i加載到操做數棧
  3. 把棧頂的值存儲到指定變量的位置

i++會先把i的值加載到操做數棧,因此語句中使用的是自增前的值,而++i會先對i自增後在加載到棧頂,因此使用的是自增後的值安全

用過JPA嗎,裏面的@Version用過嗎?

@Version註解是用於檢測併發修改操做的,當發生這種狀況時會拋出一個事務異常數據結構

@Version是基於樂觀鎖原理(版本號)保證字段的併發修改安全性,若是樂觀鎖更新失敗會拋出ObjectOptimisticLockingFailureException異常多線程

線程池的狀態有哪幾種?

在ThreadPoolExecutor中,其類變量ctl的高三位表明線程池狀態:併發

  • RUNNING:運行狀態,正常工做
  • SHUTDOWN:關閉狀態,不接受新任務,但會處理在阻塞隊列中排隊的隊伍
  • STOP:中止狀態,不接受新任務,也不處理排隊的任務,同時會中斷執行中的任務
  • TIDYING:整理狀態,全部任務終止,沒有工做線程,即將運行terminated方法來終結線程池
  • TERMINATED:終結狀態,terminated方法結束後線程池終結

狀態的轉換經過如下方式:性能

圖1

Java原生的序列化是怎麼實現的?

將一個對象的內容按如下格式存儲爲二進制文件:

  1. 序列化文件頭:聲明序列化協議和版本等信息
  2. 類描述:聲明類名和域個數等信息,序列化id在此處聲明
  3. 屬性描述:聲明域類型和名稱,注意,此處不聲明屬性的值
  4. 父類信息描述:若是有,則和類描述部分一致
  5. 屬性值:保存屬性的值

講一下建造者模式

建造者模式是將多個簡單的對象一步步構建成一個複雜的對象,將複雜對象的構建表示相分離,使得一樣的構建過程能夠建立不一樣的表示

經過建造者模式,能夠統一流程化的裝配過程,相比於工廠模式,建造者模式更關注於零件裝配的順序

當須要建立複雜對象時,且內部變化不復雜時,可使用建造者模式,更加精細地控制對象建造過程,同時將對象自己與對象的建立過程解耦,讓客戶端不須要知道內部組成的細節

JDK對synchronized關鍵字作了哪些優化?

鎖膨脹

通常地,咱們理解的synchronized屬於重量級鎖,在其下JDK提供了兩種更輕量級的鎖,分別是偏向鎖和輕量級鎖:

  • 偏向鎖:不進行加鎖,而是在對象頭設置「01」標誌位,表示偏向模式。持有偏向鎖的線程再次進入與該鎖相關的同步塊時,只要檢查設置的線程id是否與自身一致,若是一致則能夠直接進入,省去了加鎖操做。等待全局安全點[3]時會撤銷該鎖
  • 輕量級鎖:在運行到同步塊時,JVM會在當前線程棧幀中創建一個Lock Record的空間,用於存儲鎖對象的Mark Word的拷貝,而後嘗試使用CAS操做將對象的Mark Word指向Lock Record,若是更新成功,則線程獲取同步鎖,並將鎖標誌位改成「00」

鎖膨脹指的是,一開始使用偏向鎖來進行同步,若是有其餘線程進入同步塊,則鎖膨脹爲輕量級鎖,在輕量級鎖的狀況下,若是CAS更新失敗,則鎖膨脹爲重量級鎖

偏向鎖保證了單線程的執行效率,輕量級鎖保證了多線程可是幾乎沒有競爭的狀況下的效率

鎖粗化

將屢次鏈接在一次的加鎖和解鎖操做合併爲一次,擴展爲一個更大的鎖

鎖消除

對於一些不可能存在共享數據競爭的鎖[4]進行消除

redis的各類數據結構各自有什麼應用場景?

  • string:計數器、存儲圖片(基於redis二進制存儲安全性)
  • hash:大量數據存儲、存儲對象的屬性信息
  • list:消息隊列、分頁查詢(基於range命令)
  • set:數據去重、集合運算
  • zset:topN、範圍查找

瞭解自適應哈希嗎,簡單講一下

Innodb引擎會監控對錶上索引的查找[5],若是觀察到創建hash索引會帶來性能的提高,就會創建hash索引,稱爲自適應哈希

自適應哈希是經過緩衝池的B+樹構造而來,因此創建的速度很快,並且不須要爲整張表創建索引

經過SHOW ENGINE INNODB STATUS能夠查看索引的使用狀況

SQL注入有哪些方式?

  • 判斷有無注入點:get請求的參數後加單引號,若是出錯則存在注入漏洞
  • 判斷某表是否存在:~ and 0 <> (select count(*) from _table)
  • 判斷帳號個數:~ and [num] < (select count(*) from _table)
  • 判斷字段名稱:~ and 1=(select count(*) from _table where len(_name) > 0)
  • 繞過過濾:16進制繞過符號、括號或tab繞過空格、註釋符繞過關鍵字
  • 執行其餘語句:加分號,後接其餘語句
  • 更改語句條件:~ and 1=0 or [condition]

什麼是覆蓋索引

若是一個索引包含全部須要查詢的字段的值,搜索時只需掃描索引,而無需全表掃描,則稱爲覆蓋索引

在explain的extra列會顯示using index,而不是using where


  1. 若是插入的數據位數大於數據本來數據的位數,會致使數據總體升級到更大的數據位數 ↩︎

  2. JVM彙編指令是對彙編指令作了一次封裝 ↩︎

  3. 在這個時間點上沒有字節碼在執行 ↩︎

  4. 好比對局部變量加鎖,且這個變量不對外輸出 ↩︎

  5. Innodb會根據訪問頻率來爲某些頁創建hash索引 ↩︎

相關文章
相關標籤/搜索