線程池使用的是哪種
ThreadPoolExecutor: 核心線程數(shù)、最大線程數(shù)、存活時間、ThreadFactory、BlockingQueue任務(wù)隊列、RejectedExecutionHandler拒絕策略
4種拒絕策略:當(dāng)隊列(有界隊列)任務(wù)已滿時的處理方式
1、AbortPolicy,丟棄任務(wù)并拋出RejectedExecutionExecption
2、DiscardPolicy,丟棄任務(wù)但不拋出異常
3、DiscardOldestPolicy,丟棄隊列最前面的任務(wù),然后嘗試重新執(zhí)行任務(wù)
4、CallerRunsPolicy,由調(diào)用線程處理任務(wù)
線程池參數(shù)怎么配置
參上
線程池各個參數(shù)的作用
參上
線程池的參數(shù)配置要注意什么
創(chuàng)建線程池建議采用new ThreadPoolExecutor,而不是采用Executor提供的方法來創(chuàng)建,因為Executor提供的創(chuàng)建方式線程最大數(shù)量是Integer.MAX,可能會造成OOM。
線程池的工作流程

JDK 中的并發(fā)類知道哪些
Java并發(fā)包concurrent包下的:
1、Lock, 樂觀鎖操作
2、阻塞隊列
3、原子操作類
4、線程池:Executors
5、信號量:CountDownLatch、CyclicBarrier等
AQS 的底層原理
介紹下悲觀鎖和樂觀鎖
使用過哪些鎖?
syncronized
RenrtrrentLock:重入鎖,sync和RentrentLock都是重入鎖,重入鎖是為了解決線程死鎖問題。
CAS
synchronized?和?Lock?的區(qū)別、使用場景
1、sync是jvm層面處理的,是一個關(guān)鍵字,而Lock是一個類
當(dāng)使用sync同步代碼塊的時候,可以通過查看class字節(jié)碼看到:
```
public class SyncDemo{
? ? public synchronized void test1(){
????}
? ? public void test2(){
? ? ? ? synchronized (this){
????????}
????}
}
```

2、sync是直接通過加鎖,屬于悲觀鎖,而Lock使用CAS機制,是樂觀鎖。
3、sync會自動釋放鎖,而lock需要手動釋放,并且需要try、catch、finally中最終釋放(防止死鎖)
synchronized?原理
Java的對象存儲主要分為以下三個部分:

對象頭包括兩部分數(shù)據(jù):MarkWord以及類型指針(Class MetaData Address)指向當(dāng)前對象的類元數(shù)據(jù)
MarkWord是非固定結(jié)構(gòu)的數(shù)據(jù),主要存儲了對象的HashCode、鎖狀態(tài)、鎖標(biāo)記位等,根據(jù)對象的鎖狀態(tài),鎖存儲的數(shù)據(jù)也有所不同。

JDK1.6之前,僅有重量級鎖的概念,重量級鎖也就是同步鎖,會造成線程阻塞,并且會使線程在用戶態(tài)與核心態(tài)頻繁切換,影響效率。而在JDK1.6,JVM對synchnorized做了較大的優(yōu)化,引入了偏向鎖、輕量鎖。對象不會一創(chuàng)建就處于重量級鎖的狀態(tài),而是按照一定的規(guī)則升級。
鎖升級過程:
1、對象在創(chuàng)建初期,此時沒有任何線程競爭,lock的標(biāo)記位是01,偏向鎖標(biāo)記位0

2、當(dāng)有線程來競爭鎖時,將升級為偏向鎖,在標(biāo)記字(MarkWord)中記錄該線程的ID,此后該線程訪問此對象時不需要再做任何檢驗和切換,此時的線程執(zhí)行效率是非常高的。

3、當(dāng)有兩個線程來競爭鎖時,將升級為輕量鎖,即兩個線程公平競爭鎖,誰先獲得鎖就獲得了代碼的執(zhí)行。MarkWord將不再記錄偏向線程,而是記錄棧幀中的鎖記錄。

4、當(dāng)更多的線程來競爭鎖時,輕量鎖將升級為重量鎖,此時MarkWord記錄一個監(jiān)視器的對象(ObjectMintor)

synchronized?作用于靜態(tài)方法、普通方法、this、Lock.class?的區(qū)別
靜態(tài)方法,鎖的是this.class(類對象),普通方法鎖的是this
為什么引入偏向鎖、輕量級鎖,介紹下升級流程
升級流程如上上個問題
死鎖的必要條件,如何預(yù)防死鎖
1、互斥條件:一個資源只能被一個線程占有
2、請求與保持條件:至少保持了一個占有資源,又去請求其它的資源,此時線程阻塞,但是對已獲得的資源不釋放
3、不可剝奪條件:線程已經(jīng)獲取的資源,不能被其它線程占有,只能等待當(dāng)前線程主動釋放
4、循環(huán)等待條件:若干線程形成收尾相接循環(huán)等待的關(guān)系
破壞死鎖:由于線程的互斥是不可改變的,那么只能從其它三個方面去破壞死鎖。
1、破壞不可剝脫條件:當(dāng)發(fā)現(xiàn)不能獲取執(zhí)行所需的全部資源時,則處于等待狀態(tài),當(dāng)可以獲取到全部資源時,才執(zhí)行。
2、破壞請求保持:
3、破壞循環(huán)等待:將資源進行編號,按照資源緊缺,越緊缺編號越大,只有當(dāng)線程可以獲取到編號最小的資源時,才執(zhí)行。
介紹下 CountDownLatch?和 CyclicBarrier
兩者都是用來做同步輔助控制的,CountDownLatch,執(zhí)行的當(dāng)前線程會處于阻塞狀態(tài),等到所有線程都執(zhí)行完畢,才會進入下一步,不可循環(huán)。而CyclicBarrier執(zhí)行的當(dāng)前線程不會阻塞,是一種異步操作,而且是可循環(huán)的。
介紹下 CAS,存在什么問題
?CAS,Compare And Swap 比較并替換。
是一種樂觀鎖,在更新數(shù)據(jù)的時候,將數(shù)據(jù)與內(nèi)存中的數(shù)據(jù)進行比較,如果發(fā)現(xiàn)一致,則可以更新為新的值,不一致則獲取最新的值并重新執(zhí)行以上流程。
1、ABA問題,內(nèi)存中的值可能經(jīng)過A 修改為B 后又修改為A,如果僅僅比較值,可能是一樣的,那么這種改變對程序是不可見的,可以通過加版本號解決,每次修改,將版本號加1
2、自旋問題:某個線程可能會一直處于自旋(循環(huán))狀態(tài),此時的CPU開銷是比較大的
介紹下 ThreadLocal,存在什么問題
同一個ThreadLocal對象在不同線程中有不同的數(shù)據(jù)副本,其數(shù)據(jù)結(jié)構(gòu)采用ThreadLocalMap實現(xiàn),每個線程創(chuàng)建的時候,set數(shù)據(jù)的時候,會有線程作為key,vlaue作為值存入ThreadLocalMap中
存在問題:
1、ThreadLocalMap的key采用的是弱引用,可以保證在在線程執(zhí)行完畢之后key可以被回收,但是value是強引用,任然需要手動回收,否則可能會造成內(nèi)存泄漏。
2、線程池數(shù)據(jù)錯亂:因為現(xiàn)在使用的基本都是線程池,那么在不同的時間執(zhí)行的方法使用的線程可能是同一個,如果在ThreadLocal中set了值而沒有清理,則可能會造成數(shù)據(jù)錯亂,使用remove來清理數(shù)據(jù)保證數(shù)據(jù)干凈。
使用場景:?
1、Spring采用ThreadLocal解決事務(wù)控制的問題:一個業(yè)務(wù)方法中,可能調(diào)用了很多個Mapper接口的方法,要實現(xiàn)事務(wù)控制,必須保證這些Mapper使用的數(shù)據(jù)庫連接是同一個。 同時Spring的事務(wù)傳播機制不同,事務(wù)的處理邏輯也是不一樣的。比如:A方法調(diào)用B方法,? A的事務(wù)處理與B的事務(wù)處理邏輯分開,那么A方法和B方法所使用的數(shù)據(jù)庫連接則不能是同一個。
2、數(shù)據(jù)傳輸:一個變量在多個類、方法都使用到,要保證其線程安全,可以通過方法傳遞的方式,也可以通過ThreadLocal來實現(xiàn)。