亚洲日本色色一区|99视频在线看观免费|亚洲国产日本综合aⅴ|欧美一区二区a片在线视频|亚洲成AV人在线观看影院|国产免费私拍一区二区三区|亚洲中文有码字幕日本第一页|亚洲欧洲日韩国产一区二区三区

面向面試編程連載(二)_全球時快訊

Spring 依賴注入概念和@Autowired 的用法。

概念:實例不再由程序員實例化,而是通過spring容器幫我們new指定實例并且將實例注入到需要該對象的類。依賴注入能夠讓相互協(xié)作的軟件組件保持松散耦合@Autowired 注釋,它可以對類成員變量、方法及構造函數(shù)進行標注,完成自動裝配的工作。 通過 @Autowired的使用來消除 set ,get方法。也可作用與集合上這里授權服務配置類是繼承了AuthorizationServerConfigurerAdapter,而AuthorizationServerConfigurerAdapter又實現(xiàn)了AuthorizationServerConfigurer接口!源碼AuthorizationServerConfigurer@Autowired對List自動注入//@Autowired注解用在接口的集合上面,所有實現(xiàn)該接口的實現(xiàn)類都會在該集合中@Autowired(required = false)private List tasks = Collections.emptyList();

Spring Bean 的生命周期。

Bean 的生命周期概括起來就是 4 個階段:

實例化(Instantiation)

屬性賦值(Populate)


【資料圖】

初始化(Initialization)

銷毀(Destruction)

Spring Bean 的生命周期

Spring Boot 啟動流程以及底層源碼

Spring Boot 啟動流程以及底層源碼

索引的數(shù)據(jù)結構(比如 B+樹)

B+TreeB+Tree相對于B-Tree有幾點不同:非葉子節(jié)點只存儲鍵值信息。所有葉子節(jié)點之間都有一個鏈指針。數(shù)據(jù)記錄都存放在葉子節(jié)點中。查詢速度快,但是占用空間索引結構:B-Tree B+Tree B:balanceB-Tree:平衡二叉樹特點:1.具有數(shù)據(jù)節(jié)點2.指向下層指針3.指向數(shù)據(jù)指針缺頁查詢,產生IOB+Tree:特點:1.具有數(shù)據(jù)節(jié)點2.指向下層指針命中數(shù)據(jù)3層查找后查詢數(shù)據(jù)指針加載更快,產生更少IO效率:BTree更高,但從IO角度,Mysql選擇B+TreeHash 索引的特點Hash 索引只能夠用于使用 = 或者 <=> 運算符的相等比較(但是速度更快)。Hash 索引不能夠用于諸如 < 等用于查找一個范圍值的比較運算符。依賴于這種單值查找的系統(tǒng)被稱為 “鍵-值存儲”;對于這種系統(tǒng),盡可能地使用 hash 索引。優(yōu)化器不能夠使用 hash 索引來加速 ORDER BY 操作。這種類型的索引不能夠用于按照順序查找下一個條目。MySql 無法使用 hash 索引估計兩個值之間有多少行(這種情況由范圍優(yōu)化器來決定使用哪個索引)。如果你將一張 MyISAM 或 InnoDB 表轉換成一個 hash 索引的內存表時,一些查詢可能會受此影響。查找某行記錄必須進行全鍵匹配。而 B-tree 索引,任何該鍵的左前綴都可用以查找記錄

索引是為了加速對表中數(shù)據(jù)行的檢索而創(chuàng)建的一種分散的存儲結構

建索引的語句

CREATE INDEX idx_xxx USING BTREE ON tablename (字段,字段,字段);

索引的種類尤其是復合索引以及對應的回表和最左匹配原則

普通索引:最基本的索引,沒有任何約束限制。唯一索引:和普通索引類似,但是具有唯一性約束,可以有 null主鍵索引:特殊的唯一索引,不允許有 null,一張表最多一個主鍵索引組合索引:多列值組成一個索引,用于組合搜索,效率大于索引合并全文索引:對文本的內容進行分詞、搜索覆蓋索引:查詢列要被所建的索引覆蓋,不必讀取數(shù)據(jù)行1、復合索引綁定的第一個列,沒有出現(xiàn)在查詢條件中;舉例說明:為emp表插入索引idx_age_deptid_name(age,deptid,name),但是在查詢條件中未使用age,導致復合索引全部失效。2、復合索引綁定的多個列是有順序的,某一個列沒有出現(xiàn)在查詢條件中,存儲引擎不能使用索引中該列及其后的所有列。舉例:為emp表插入索引idx_age_deptid_name(age,deptid,name),查詢時查詢條件里沒有deptid列,會導致復合索引中的deptid及其后的索引失效。3.查詢條件中出現(xiàn)某個列是范圍查詢的,存儲引擎不能使用復合索引中該列其后的所有列。舉例:為emp表插入索引idx_age_deptid_name(age,deptid,name),查詢時查詢條件里deptid列使用到了范圍查詢,會導致復合索引中的deptid其后的索引失效。4.查詢條件中某列使用否定條件的(!= <> IS NOT NULL),存儲引擎不能使用索引中該列其后的所有列。舉例:為emp表插入索引idx_age_deptid_name(age,deptid,name),查詢時查詢條件里deptid列使用到了否定條件,會導致復合索引中的deptid其后的索引失效。5.查詢條件中某列使用LIKE條件后的字段是以%開頭的(如:’%ABC’),存儲引擎不能使用索引中該列及其后的所有列。舉例:為emp表插入索引idx_age_deptid_name(age,deptid,name),查詢時查詢條件里name列使用到了like ‘%a’,會導致復合索引中的name及其后的索引失效。6.查詢條件中某列使用函數(shù)的,存儲引擎不能使用索引中該列及其后的所有列。舉例:為emp表插入索引idx_age_deptid_name(age,deptid,name),查詢時查詢條件里name列使用到了like ‘%a’,會導致復合索引中的name及其后的索引失效。7.查詢條件中某列使用類型轉換的(包括顯示的和隱示的),存儲引擎不能使用索引中該列及其后的所有列。如:字符串類型的列NAME=3,就是隱示的類型轉換,將INT型轉換為字符串類型。如果寫為NAME=’3’,就不是類型轉換。舉例:為emp表插入索引idx_age_deptid_name(age,deptid,name),查詢時查詢條件name=3,會導致復合索引中的name及其后的索引失效。條件寫成name=‘3’,索引就不會失效。

回表

如果索引的列在 select 所需獲得的列中(因為在 mysql 中索引是根據(jù)索引列的值進行排序的,所以索引節(jié)點中存在該列中的部分值)或者根據(jù)一次索引查詢就能獲得記錄就不需要回表,如果 select 所需獲得列中有大量的非索引列,索引就需要到表中找到相應的列的信息,這就叫回表。

使用聚集索引(主鍵或第一個唯一索引)就不會回表,普通索引就會回表

索引下推優(yōu)化,

可以在索引遍歷過程中,對索引中包含的字段先做判斷,過濾掉不符合條件的記錄,減少回表字數(shù)。

最左匹配原則

帶頭大哥不能死,中間兄弟不能斷

Spring AOP 底層原理

AOP 底層是采用動態(tài)代理機制實現(xiàn)的:接口+實現(xiàn)類

如果要代理的對象,實現(xiàn)了某個接口,那么 Spring AOP 會使用 JDK Proxy,去創(chuàng)建代

理對象。

沒有實現(xiàn)接口的對象,就無法使用 JDK Proxy 去進行代理了,這時候 Spring AOP 會使用

Cglib 生成一個被代理對象的子類來作為代理。

就是由代理創(chuàng)建出一個和 impl 實現(xiàn)類平級的一個對象,但是這個對象不是一個真正的對象,

只是一個代理對象,但它可以實現(xiàn)和 impl 相同的功能,這個就是 aop 的橫向機制原理,這

樣就不需要修改源代碼。

HashMap在java1.7之前底層數(shù)據(jù)結構是數(shù)組+鏈表,1.8之后是數(shù)組+鏈表+紅黑樹,

在1.7以前的put方法采用的是頭插法,當hash碰撞次數(shù)到達8,且桶內元素到達64個的時候形成鏈表,但是在極端情況下會造成鏈表過長,效率變低,并且在rehash的時候,頭插法會造成回環(huán)鏈首尾相連,形成死鎖,在java1.8以后采用紅黑樹,除了添加效率都高,是線程不安全的,不安全示例

public class HashMapTest {    public static void main(String[] args) {        HashMapThread thread0 = new HashMapThread();        HashMapThread thread1 = new HashMapThread();        HashMapThread thread2 = new HashMapThread();        HashMapThread thread3 = new HashMapThread();        HashMapThread thread4 = new HashMapThread();        thread0.start();        thread1.start();        thread2.start();        thread3.start();        thread4.start();    }}class HashMapThread extends Thread {    private static AtomicInteger ai = new AtomicInteger();    private static Map map = new HashMap<>();    @Override    public void run() {        while (ai.get() < 1000000) {            map.put(ai.get(), ai.get());            ai.incrementAndGet();        }    }}

JDK1.8 之前

JDK1.8 之前 HashMap 底層是 數(shù)組和鏈表 結合在一起使用也就是 鏈表散列。 ## HashMap 通過 key 的 hashCode 經過擾動函數(shù)處理過后得到 hash 值,然后通過 (n -

1) & hash 判斷當前元素存放的位置(這里的 n 指的是數(shù)組的長度),如果當前位置存在

元素的話,就判斷該元素與要存入的元素的 hash 值以及 key 是否相同,如果相同的話,

直接覆蓋,不相同就通過拉鏈法解決沖突。

所謂擾動函數(shù)指的就是 HashMap 的 hash 方法。使用 hash 方法也就是擾動函數(shù)是為了

防止一些實現(xiàn)比較差的 hashCode() 方法 換句話說使用擾動函數(shù)之后可以減少碰撞。

JDK1.8 之后

當鏈表長度大于閾值(默認為 8)時,會首先調用 treeifyBin()方法。這個方法會根據(jù)

HashMap 數(shù)組來決定是否轉換為紅黑樹。只有當數(shù)組長度大于或者等于 64 的情況下,才會

執(zhí)行轉換紅黑樹操作,以減少搜索時間。否則,就是只是執(zhí)行 resize() 方法對數(shù)組擴容。

1.通常代替HashMap的安全由HashTable代替,但是多線程下他的put.get方法都是synchronized,效率太低,

2.Collections.synchronizedMap(),底層仍是synchronized

3.java9實現(xiàn)Collections.of()

ConcurrentHashMap 與 ConcurrentSkipListMap

ConcurrentHashMap 加鎖

ConcurrentSkipListMap 不需要加鎖,浪費空間,

4.ConcurrentHashMap

ConcurrentHashMap如何保證線程安全,在1.7以前由劃分segment分段鎖機制,共計16個并發(fā)級別,隔離級別太大,有很多空間就浪費了,太小就段內的元素過多

1.8以后是cas算法C語言寫得,無鎖算法,put添加的時候,鏈表+紅黑樹

put方法(無鎖添加)

3、HashMap 的擴容機制是怎樣的?

一般情況下,當元素數(shù)量超過閾值時便會觸發(fā)擴容。每次擴容的容量都是之前容量的 2 倍。

HashMap 的容量是有上限的,必須小于 1<<30,即 1073741824。如果容量超出了這個

數(shù),則不再增長,且閾值會被設置為 Integer.MAX_VALUE。

JDK7 中的擴容機制

空參數(shù)的構造函數(shù):以默認容量、默認負載因子、默認閾值初始化數(shù)組。內部數(shù)組是空數(shù)

組。

有參構造函數(shù):根據(jù)參數(shù)確定容量、負載因子、閾值等。

第一次 put 時會初始化數(shù)組,其容量變?yōu)椴恍∮谥付ㄈ萘康?2 的冪數(shù),然后根據(jù)負載因子

確定閾值。

如果不是第一次擴容,則 新容量=舊容量 x 2 ,新閾值=新容量 x 負載因子 。

JDK8 的擴容機制

空參數(shù)的構造函數(shù):實例化的 HashMap 默認內部數(shù)組是 null,即沒有實例化。第一次調

用 put 方法時,則會開始第一次初始化擴容,長度為 16。 ## 有參構造函數(shù):用于指定容量。會根據(jù)指定的正整數(shù)找到不小于指定容量的 2 的冪數(shù),將

這個數(shù)設置賦值給閾值(threshold)。第一次調用 put 方法時,會將閾值賦值給容量,

然后讓 閾值 = 容量 x 負載因子。 ## 如果不是第一次擴容,則容量變?yōu)樵瓉淼?2 倍,閾值也變?yōu)樵瓉淼?2 倍。(容量和閾值都

變?yōu)樵瓉淼?2 倍時,負載因子還是不變)。

此外還有幾個細節(jié)需要注意:

首次 put 時,先會觸發(fā)擴容(算是初始化),然后存入數(shù)據(jù),然后判斷是否需要擴容;

不是首次 put,則不再初始化,直接存入數(shù)據(jù),然后判斷是否需要擴容;

4、ConcurrentHashMap 的存儲結構是怎樣的?

Java7 中 ConcurrnetHashMap 使用的分段鎖,也就是每一個 Segment 上同時只有一個

線程可以操作,每一個 Segment 都是一個類似 HashMap 數(shù)組的結構,它可以擴容,它

的沖突會轉化為鏈表。但是 Segment 的個數(shù)一但初始化就不能改變,默認 Segment 的

個數(shù)是 16 個。

Java8 中的 ConcurrnetHashMap 使用的 Synchronized 鎖加 CAS 的機制。結構也由

Java7 中的 Segment 數(shù)組 + HashEntry 數(shù)組 + 鏈表 進化成了 Node 數(shù)組 + 鏈表 / 紅

黑樹,Node 是類似于一個 HashEntry 的結構。它的沖突再達到一定大小時會轉化成紅

黑樹,在沖突小于一定數(shù)量時又退回鏈表。

5、線程池大小如何設置?

CPU 密集型任務(N+1): 這種任務消耗的主要是 CPU 資源,可以將線程數(shù)設置為 N (CPU 核心數(shù))+1,比 CPU 核心數(shù)多出來的一個線程是為了防止線程偶發(fā)的缺頁中斷,

或者其它原因導致的任務暫停而帶來的影響。一旦任務暫停,CPU 就會處于空閑狀態(tài),而

在這種情況下多出來的一個線程就可以充分利用 CPU 的空閑時間。

I/O 密集型任務(2N): 這種任務應用起來,系統(tǒng)會用大部分的時間來處理 I/O 交互,而

線程在處理 I/O 的時間段內不會占用 CPU 來處理,這時就可以將 CPU 交出給其它線程

使用。因此在 I/O 密集型任務的應用中,我們可以多配置一些線程,具體的計算方法是

2N。

如何判斷是 CPU 密集任務還是 IO 密集任務?

CPU 密集型簡單理解就是利用 CPU 計算能力的任務比如你在內存中對大量數(shù)據(jù)進行排序。單

凡涉及到網絡讀取,文件讀取這類都是 IO 密集型,這類任務的特點是 CPU 計算耗費時間相

比于等待 IO 操作完成的時間來說很少,大部分時間都花在了等待 IO 操作完成上。

6、IO 密集=Ncpu*2 是怎么計算出來?

I/O 密集型任務任務應用起來,系統(tǒng)會用大部分的時間來處理 I/O 交互,而線程在處理

I/O 的時間段內不會占用 CPU 來處理,這時就可以將 CPU 交出給其它線程使用。因此在

I/O 密集型任務的應用中,我們可以多配置一些線程。例如:數(shù)據(jù)庫交互,文件上傳下

載,網絡傳輸?shù)?。IO 密集型,即該任務需要大量的 IO,即大量的阻塞,故需要多配置線

程數(shù)。

7、G1 收集器有哪些特點?

G1 的全稱是 Garbage-First,意為垃圾優(yōu)先,哪一塊的垃圾最多就優(yōu)先清理它。

G1 GC 最主要的設計目標是:將 STW 停頓的時間和分布,變成可預期且可配置的。

被視為 JDK1.7 中 HotSpot 虛擬機的一個重要進化特征。它具備一下特點:

并行與并發(fā):G1 能充分利用 CPU、多核環(huán)境下的硬件優(yōu)勢,使用多個 CPU(CPU 或者

CPU 核心)來縮短 Stop-The-World 停頓時間。部分其他收集器原本需要停頓 Java 線程

執(zhí)行的 GC 動作,G1 收集器仍然可以通過并發(fā)的方式讓 java 程序繼續(xù)執(zhí)行。

分代收集:雖然 G1 可以不需要其他收集器配合就能獨立管理整個 GC 堆,但是還是保留

了分代的概念。

空間整合:與 CMS 的“標記-清理”算法不同,G1 從整體來看是基于“標記-整理”算法

實現(xiàn)的收集器;從局部上來看是基于“標記-復制”算法實現(xiàn)的。

可預測的停頓:這是 G1 相對于 CMS 的另一個大優(yōu)勢,降低停頓時間是 G1 和 CMS 共

同的關注點,但 G1 除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明

確指定在一個長度為 M 毫秒的時間片段內。

G1 收集器在后臺維護了一個優(yōu)先列表,每次根據(jù)允許的收集時間,優(yōu)先選擇回收價值最大的

Region(這也就是它的名字 Garbage-First 的由來)

8、你有哪些手段來排查 OOM 的問題?

增加兩個參數(shù) -XX:+HeapDumpOnOutOfMemoryError -

XX:HeapDumpPath=/tmp/heapdump.hprof,當 OOM 發(fā)生時自動 dump 堆內存信

息到指定目錄。

同時 jstat 查看監(jiān)控 JVM 的內存和 GC 情況,先觀察問題大概出在什么區(qū)域。

使用 MAT 工具載入到 dump 文件,分析大對象的占用情況,比如 HashMap 做緩存未

清理,時間長了就會內存溢出,可以把改為弱引用。

image.png

標簽: 編程算法 HashMap Spring

<< 上一篇
下一篇 >>
  • 精心推薦