自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

秒掛了!與快手無緣了....

開發(fā) 前端
當(dāng)線程池的任務(wù)隊(duì)列滿了之后,線程池會執(zhí)行指定的拒絕策略來應(yīng)對,常用的四種拒絕策略包括:CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy,此外,還可以通過實(shí)現(xiàn)RejectedExecutionHandler接口來自定義拒絕策略。

大家好,我是小林。

今天分享一位同學(xué)快手Java后端面經(jīng),問的問題基礎(chǔ)比較多,可惜同學(xué)沒怎么準(zhǔn)備好,回答的不是很多,面完就秒掛了。

圖片圖片

考察的知識,我給大家羅列一下:

  • 操作系統(tǒng):進(jìn)程線程、上下文、中斷
  • Java:JVM、HashMap、synchronized、線程池
  • 數(shù)據(jù)結(jié)構(gòu):數(shù)組和鏈表
  • 算法:合并k個(gè)有序鏈表

技術(shù)八股

進(jìn)程和線程區(qū)別是什么?

圖片圖片

  • 本質(zhì)區(qū)別:進(jìn)程是操作系統(tǒng)資源分配的基本單位,而線程是任務(wù)調(diào)度和執(zhí)行的基本單位
  • 在開銷方面:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間(程序上下文),程序之間的切換會有較大的開銷;線程可以看做輕量級的進(jìn)程,同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程都有自己獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器(PC),線程之間切換的開銷小
  • 穩(wěn)定性方面:進(jìn)程中某個(gè)線程如果崩潰了,可能會導(dǎo)致整個(gè)進(jìn)程都崩潰。而進(jìn)程中的子進(jìn)程崩潰,并不會影響其他進(jìn)程。
  • 內(nèi)存分配方面:系統(tǒng)在運(yùn)行的時(shí)候會為每個(gè)進(jìn)程分配不同的內(nèi)存空間;而對線程而言,除了CPU外,系統(tǒng)不會為線程分配內(nèi)存(線程所使用的資源來自其所屬進(jìn)程的資源),線程組之間只能共享資源
  • 包含關(guān)系:沒有線程的進(jìn)程可以看做是單線程的,如果一個(gè)進(jìn)程內(nèi)有多個(gè)線程,則執(zhí)行過程不是一條線的,而是多條線(線程)共同完成的;線程是進(jìn)程的一部分,所以線程也被稱為輕權(quán)進(jìn)程或者輕量級進(jìn)程

什么是上下文?

任務(wù)是交給 CPU 運(yùn)行的,那么在每個(gè)任務(wù)運(yùn)行前,CPU 需要知道任務(wù)從哪里加載,又從哪里開始運(yùn)行所以,操作系統(tǒng)需要事先幫 CPU 設(shè)置好 CPU 寄存器和程序計(jì)數(shù)器。

CPU 寄存器和程序計(jì)數(shù)是 CPU 在運(yùn)行任何任務(wù)前,所必須依賴的環(huán)境,這些環(huán)境就叫做 CPU 上下文。

CPU 上下文切換就是先把前一個(gè)任務(wù)的 CPU 上下文(CPU 寄存器和程序計(jì)數(shù)器)保存起來,然后加載新任務(wù)的上下文到這些寄存器和程序計(jì)數(shù)器,最后再跳轉(zhuǎn)到程序計(jì)數(shù)器所指的新位置,運(yùn)行新任務(wù)。

系統(tǒng)內(nèi)核會存儲保持下來的上下文信息,當(dāng)此任務(wù)再次被分配給 CPU 運(yùn)行時(shí),CPU 會重新加載這些上下文,這樣就能保證任務(wù)原來的狀態(tài)不受影響,讓任務(wù)看起來還是連續(xù)運(yùn)行。

上面說到所謂的「任務(wù)」,主要包含進(jìn)程、線程和中斷。所以,可以根據(jù)任務(wù)的不同,把 CPU 上下文切換分成:進(jìn)程上下文切換、線程上下文切換

進(jìn)程是由內(nèi)核管理和調(diào)度的,所以進(jìn)程的切換只能發(fā)生在內(nèi)核態(tài)。所以,進(jìn)程的上下文切換不僅包含了虛擬內(nèi)存、棧、全局變量等用戶空間的資源,還包括了內(nèi)核堆棧、寄存器等內(nèi)核空間的資源。

通常,會把交換的信息保存在進(jìn)程的 PCB,當(dāng)要運(yùn)行另外一個(gè)進(jìn)程的時(shí)候,我們需要從這個(gè)進(jìn)程的 PCB 取出上下文,然后恢復(fù)到 CPU 中,這使得這個(gè)進(jìn)程可以繼續(xù)執(zhí)行,如下圖所示:

圖片圖片

線程共享進(jìn)程的虛擬內(nèi)存資源,但是線程也有自己的私有數(shù)據(jù),比如棧和寄存器等,這些在上下文切換時(shí)也是需要保存的。

線程上下文切換時(shí),虛擬內(nèi)存這些資源就保持不動,只需要切換線程的私有數(shù)據(jù)、寄存器等不共享的數(shù)據(jù)。

什么是中斷?

CPU停下當(dāng)前的工作任務(wù),去處理其他事情,處理完后回來繼續(xù)執(zhí)行剛才的任務(wù),這一過程便是中斷。

中斷分為外部中斷和內(nèi)部中斷:

  • 外部中斷分為可屏蔽中斷和不可屏蔽中斷:
  • 可屏蔽中斷:通過INTR線向CPU請求的中斷,主要來自外部設(shè)備如硬盤,打印機(jī),網(wǎng)卡等。此類中斷并不會影響系統(tǒng)運(yùn)行,可隨時(shí)處理,甚至不處理,所以名為可屏蔽。
  • 不可屏蔽中斷:通過NMI線向CPU請求的中斷,如電源掉電,硬件線路故障等。這里不可屏蔽的意思不是不可以屏蔽,不建議屏蔽,而是問題太大,屏蔽不了,不能屏蔽的意思。注:INTR和NMI都是CPU的引腳
  • 內(nèi)部中斷分為陷阱、故障、終止:
  • 陷阱:是一種有意的,預(yù)先安排的異常事件,一般是在編寫程序時(shí)故意設(shè)下的陷阱指令,而后執(zhí)行到陷阱指令后,CPU將會調(diào)用特定程序進(jìn)行相應(yīng)的處理,處理結(jié)束后返回到陷阱指令的下一條指令。如系統(tǒng)調(diào)用,程序調(diào)試功能等。如printf函數(shù),最底層的實(shí)現(xiàn)中會有一條int 0x80指令,這就是一條陷阱指令,使用0x80號中斷進(jìn)行系統(tǒng)調(diào)用。

  • 故障:故障是在引起故障的指令被執(zhí)行,但還沒有執(zhí)行結(jié)束時(shí),CPU檢測到的一類的意外事件。出錯(cuò)時(shí)交由故障處理程序處理,如果能處理修正這個(gè)錯(cuò)誤,就將控制返回到引起故障的指令即CPU重新執(zhí)這條指令。如果不能處理就報(bào)錯(cuò)。常見的故障為缺頁,當(dāng)CPU引用的虛擬地址對應(yīng)的物理頁不存在時(shí)就會發(fā)生故障。缺頁異常是能夠修正的,有著專門的缺頁處理程序,它會將缺失的物理頁從磁盤中重新調(diào)進(jìn)主存。而后再次執(zhí)行引起故障的指令時(shí)便能夠順利執(zhí)行了。

  • 終止:執(zhí)行指令的過程中發(fā)生了致命錯(cuò)誤,不可修復(fù),程序無法繼續(xù)運(yùn)行,只能終止,通常會是一些硬件的錯(cuò)誤。終止處理程序不會將控制返回給原程序,而是直接終止原程序

數(shù)組和鏈表區(qū)別是什么?

  • 訪問效率:數(shù)組可以通過索引直接訪問任何位置的元素,訪問效率高,時(shí)間復(fù)雜度為O(1),而鏈表需要從頭節(jié)點(diǎn)開始遍歷到目標(biāo)位置,訪問效率較低,時(shí)間復(fù)雜度為O(n)。
  • 插入和刪除操作效率:數(shù)組插入和刪除操作可能需要移動其他元素,時(shí)間復(fù)雜度為O(n),而鏈表只需要修改指針指向,時(shí)間復(fù)雜度為O(1)。
  • 緩存命中率:由于數(shù)組元素在內(nèi)存中連續(xù)存儲,可以提高CPU緩存的命中率,而鏈表節(jié)點(diǎn)不連續(xù)存儲,可能導(dǎo)致CPU緩存的命中率較低,頻繁的緩存失效會影響性能。
  • 應(yīng)用場景:數(shù)組適合靜態(tài)大小、頻繁訪問元素的場景,而鏈表適合動態(tài)大小、頻繁插入、刪除操作的場景

為什么數(shù)組查詢的復(fù)雜度為O(1)?

數(shù)組必須要內(nèi)存中一塊連續(xù)的空間,并且數(shù)組中必須存放相同的數(shù)據(jù)類型。 比如我們創(chuàng)建一個(gè)長度為 10,數(shù)據(jù)類型為整型的數(shù)組,在內(nèi)存中的地址是從 1000 開始,那么它在內(nèi)存中的存儲格式如下。

圖片圖片

由于每個(gè)整型數(shù)據(jù)占據(jù) 4 個(gè)字節(jié)的內(nèi)存空間,因此整個(gè)數(shù)組的內(nèi)存空間地址是 1000~1039,根據(jù)這個(gè),我們就可以輕易算出數(shù)組中每個(gè)數(shù)據(jù)的內(nèi)存下標(biāo)地址。 利用這個(gè)特性,我們只要知道了數(shù)組下標(biāo),也就是數(shù)據(jù)在數(shù)組中的位置,比如下標(biāo) 2,就可以計(jì)算得到這個(gè)數(shù)據(jù)在內(nèi)存中的位置 1008,從而對這個(gè)位置的數(shù)據(jù) 241 進(jìn)行快速讀寫訪問,時(shí)間復(fù)雜度為 O(1)。

JVM是什么?

JVM是 java 虛擬機(jī),主要工作是解釋自己的指令集(即字節(jié)碼)并映射到本地的CPU指令集和OS的系統(tǒng)調(diào)用。

JVM屏蔽了與操作系統(tǒng)平臺相關(guān)的信息,使得Java程序只需要生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可在多種平臺上不加修改的運(yùn)行,這也是Java能夠“一次編譯,到處運(yùn)行的”原因。

Java為什么是跨平臺的?

Java 能支持跨平臺,主要依賴于 JVM 關(guān)系比較大。

JVM也是一個(gè)軟件,不同的平臺有不同的版本。我們編寫的Java源碼,編譯后會生成一種 .class 文件,稱為字節(jié)碼文件。Java虛擬機(jī)就是負(fù)責(zé)將字節(jié)碼文件翻譯成特定平臺下的機(jī)器碼然后運(yùn)行。也就是說,只要在不同平臺上安裝對應(yīng)的JVM,就可以運(yùn)行字節(jié)碼文件,運(yùn)行我們編寫的Java程序。

而這個(gè)過程中,我們編寫的Java程序沒有做任何改變,僅僅是通過JVM這一”中間層“,就能在不同平臺上運(yùn)行,真正實(shí)現(xiàn)了”一次編譯,到處運(yùn)行“的目的。

JVM是一個(gè)”橋梁“,是一個(gè)”中間件“,是實(shí)現(xiàn)跨平臺的關(guān)鍵,Java代碼首先被編譯成字節(jié)碼文件,再由JVM將字節(jié)碼文件翻譯成機(jī)器語言,從而達(dá)到運(yùn)行Java程序的目的。

編譯的結(jié)果不是生成機(jī)器碼,而是生成字節(jié)碼,字節(jié)碼不能直接運(yùn)行,必須通過JVM翻譯成機(jī)器碼才能運(yùn)行。不同平臺下編譯生成的字節(jié)碼是一樣的,但是由JVM翻譯成的機(jī)器碼卻不一樣。

所以,運(yùn)行Java程序必須有JVM的支持,因?yàn)榫幾g的結(jié)果不是機(jī)器碼,必須要經(jīng)過JVM的再次翻譯才能執(zhí)行。即使你將Java程序打包成可執(zhí)行文件(例如 .exe),仍然需要JVM的支持。

跨平臺的是Java程序,不是JVM。JVM是用C/C++開發(fā)的,是編譯后的機(jī)器碼,不能跨平臺,不同平臺下需要安裝不同版本的JVM。

圖片圖片

Java為什么既是編譯型也是解釋型的?

首先在Java經(jīng)過編譯之后生成字節(jié)碼文件,接下來進(jìn)入JVM中,就有兩個(gè)步驟編譯和解釋。 如下圖:

圖片圖片

編譯性:

  • Java源代碼首先被編譯成字節(jié)碼,JIT 會把編譯過的機(jī)器碼保存起來,以備下次使用。

解釋性:

  • JVM中一個(gè)方法調(diào)用計(jì)數(shù)器,當(dāng)累計(jì)計(jì)數(shù)大于一定值的時(shí)候,就使用JIT進(jìn)行編譯生成機(jī)器碼文件。否則就是用解釋器進(jìn)行解釋執(zhí)行,然后字節(jié)碼也是經(jīng)過解釋器進(jìn)行解釋運(yùn)行的。

所以Java既是編譯型也是解釋性語言,默認(rèn)采用的是解釋器和編譯器混合的模式。

Python和Java區(qū)別是什么?

  • Java是一種已編譯的編程語言,Java編譯器將源代碼編譯為字節(jié)碼,而字節(jié)碼則由Java虛擬機(jī)執(zhí)行
  • python是一種解釋語言,翻譯時(shí)會在執(zhí)行程序的同時(shí)進(jìn)行翻譯。

了解HashMap嗎?

  • 在 JDK 1.7 版本之前, HashMap 數(shù)據(jù)結(jié)構(gòu)是數(shù)組和鏈表,HashMap通過哈希算法將元素的鍵(Key)映射到數(shù)組中的槽位(Bucket)。如果多個(gè)鍵映射到同一個(gè)槽位,它們會以鏈表的形式存儲在同一個(gè)槽位上,因?yàn)殒湵淼牟樵儠r(shí)間是O(n),所以沖突很嚴(yán)重,一個(gè)索引上的鏈表非常長,效率就很低了。
  • 所以在 JDK 1.8 版本的時(shí)候做了優(yōu)化,當(dāng)一個(gè)鏈表的長度超過8的時(shí)候就轉(zhuǎn)換數(shù)據(jù)結(jié)構(gòu),不再使用鏈表存儲,而是使用紅黑樹,查找時(shí)使用紅黑樹,時(shí)間復(fù)雜度O(log n),可以提高查詢性能,但是在數(shù)量較少時(shí),即數(shù)量小于6時(shí),會將紅黑樹轉(zhuǎn)換回鏈表。

圖片圖片

HashMap插入元素過程?

圖片圖片

HashMap HashMap的put()方法用于向HashMap中添加鍵值對。當(dāng)調(diào)用HashMap的put()方法時(shí),會按照以下詳細(xì)流程執(zhí)行:

第一步:根據(jù)要添加的鍵的哈希碼計(jì)算在數(shù)組中的位置(索引)。

第二步:檢查該位置是否為空(即沒有鍵值對存在)

  • 如果為空,則直接在該位置創(chuàng)建一個(gè)新的Entry對象來存儲鍵值對。將要添加的鍵值對作為該Entry的鍵和值,并保存在數(shù)組的對應(yīng)位置。將HashMap的修改次數(shù)(modCount)加1,以便在進(jìn)行迭代時(shí)發(fā)現(xiàn)并發(fā)修改。

第三步:如果該位置已經(jīng)存在其他鍵值對,檢查該位置的第一個(gè)鍵值對的哈希碼和鍵是否與要添加的鍵值對相同?

  • 如果相同,則表示找到了相同的鍵,直接將新的值替換舊的值,完成更新操作。

第四步:如果第一個(gè)鍵值對的哈希碼和鍵不相同,則需要遍歷鏈表或紅黑樹來查找是否有相同的鍵:

如果鍵值對集合是鏈表結(jié)構(gòu):

  • 從鏈表的頭部開始逐個(gè)比較鍵的哈希碼和equals()方法,直到找到相同的鍵或達(dá)到鏈表末尾。
  • 如果找到了相同的鍵,則使用新的值取代舊的值,即更新鍵對應(yīng)的值。
  • 如果沒有找到相同的鍵,則將新的鍵值對添加到鏈表的頭部。

如果鍵值對集合是紅黑樹結(jié)構(gòu):

  • 在紅黑樹中使用哈希碼和equals()方法進(jìn)行查找。根據(jù)鍵的哈希碼,定位到紅黑樹中的某個(gè)節(jié)點(diǎn),然后逐個(gè)比較鍵,直到找到相同的鍵或達(dá)到紅黑樹末尾。
  • 如果找到了相同的鍵,則使用新的值取代舊的值,即更新鍵對應(yīng)的值。
  • 如果沒有找到相同的鍵,則將新的鍵值對添加到紅黑樹中。

第五步:檢查鏈表長度是否達(dá)到閾值(默認(rèn)為8):

  • 如果鏈表長度超過閾值,且HashMap的數(shù)組長度大于等于64,則會將鏈表轉(zhuǎn)換為紅黑樹,以提高查詢效率。

第六步:檢查負(fù)載因子是否超過閾值(默認(rèn)為0.75):

  • 如果鍵值對的數(shù)量(size)與數(shù)組的長度的比值大于閾值,則需要進(jìn)行擴(kuò)容操作。

第七步:擴(kuò)容操作:

  • 創(chuàng)建一個(gè)新的兩倍大小的數(shù)組。
  • 將舊數(shù)組中的鍵值對重新計(jì)算哈希碼并分配到新數(shù)組中的位置。
  • 更新HashMap的數(shù)組引用和閾值參數(shù)。

第八步:完成添加操作。

需要注意的是,HashMap中的鍵和值都可以為null。此外,HashMap是非線程安全的,如果在多線程環(huán)境下使用,需要采取額外的同步措施或使用線程安全的ConcurrentHashMap。

重寫HashMap的equal和hashcode方法需要注意什么?

HashMap使用Key對象的hashCode()和equals()方法去決定key-value對的索引。當(dāng)我們試著從HashMap中獲取值的時(shí)候,這些方法也會被用到。如果這些方法沒有被正確地實(shí)現(xiàn),在這種情況下,兩個(gè)不同Key也許會產(chǎn)生相同的hashCode()和equals()輸出,HashMap將會認(rèn)為它們是相同的,然后覆蓋它們,而非把它們存儲到不同的地方。

同樣的,所有不允許存儲重復(fù)數(shù)據(jù)的集合類都使用hashCode()和equals()去查找重復(fù),所以正確實(shí)現(xiàn)它們非常重要。equals()和hashCode()的實(shí)現(xiàn)應(yīng)該遵循以下規(guī)則:

  • 如果o1.equals(o2),那么o1.hashCode() == o2.hashCode()總是為true的。
  • 如果o1.hashCode() == o2.hashCode(),并不意味著o1.equals(o2)會為true。

重寫HashMap的equal方法不當(dāng)會出現(xiàn)什么問題?

HashMap在比較元素時(shí),會先通過hashCode進(jìn)行比較,相同的情況下再通過equals進(jìn)行比較。

所以 equals相等的兩個(gè)對象,hashCode一定相等。hashCode相等的兩個(gè)對象,equals不一定相等(比如散列沖突的情況)

重寫了equals方法,不重寫hashCode方法時(shí),可能會出現(xiàn)equals方法返回為true,而hashCode方法卻返回false,這樣的一個(gè)后果會導(dǎo)致在hashmap等類中存儲多個(gè)一模一樣的對象,導(dǎo)致出現(xiàn)覆蓋存儲的數(shù)據(jù)的問題,這與hashmap只能有唯一的key的規(guī)范不符合,

列舉HashMap在多線程下可能會出現(xiàn)的問題?

  • JDK1.7中的 HashMap 使用頭插法插入元素,在多線程的環(huán)境下,擴(kuò)容的時(shí)候有可能導(dǎo)致環(huán)形鏈表的出現(xiàn),形成死循環(huán)。因此,JDK1.8使用尾插法插入元素,在擴(kuò)容時(shí)會保持鏈表元素原本的順序,不會出現(xiàn)環(huán)形鏈表的問題。
  • 多線程同時(shí)執(zhí)行 put 操作,如果計(jì)算出來的索引位置是相同的,那會造成前一個(gè) key 被后一個(gè) key 覆蓋,從而導(dǎo)致元素的丟失。此問題在JDK 1.7和 JDK 1.8 中都存在。

synchronized關(guān)鍵字的底層原理是什么?

synchronized是java提供的原子性內(nèi)置鎖,這種內(nèi)置的并且使用者看不到的鎖也被稱為監(jiān)視器鎖,使用synchronized之后,會在編譯之后在同步的代碼塊前后加上monitorenter和monitorexit字節(jié)碼指令,他依賴操作系統(tǒng)底層互斥鎖實(shí)現(xiàn)。他的作用主要就是實(shí)現(xiàn)原子性操作和解決共享變量的內(nèi)存可見性問題。

執(zhí)行monitorenter指令時(shí)會嘗試獲取對象鎖,如果對象沒有被鎖定或者已經(jīng)獲得了鎖,鎖的計(jì)數(shù)器+1。此時(shí)其他競爭鎖的線程則會進(jìn)入等待隊(duì)列中。

執(zhí)行monitorexit指令時(shí)則會把計(jì)數(shù)器-1,當(dāng)計(jì)數(shù)器值為0時(shí),則鎖釋放,處于等待隊(duì)列中的線程再繼續(xù)競爭鎖。

synchronized是排它鎖,當(dāng)一個(gè)線程獲得鎖之后,其他線程必須等待該線程釋放鎖后才能獲得鎖,而且由于Java中的線程和操作系統(tǒng)原生線程是一一對應(yīng)的,線程被阻塞或者喚醒時(shí)時(shí)會從用戶態(tài)切換到內(nèi)核態(tài),這種轉(zhuǎn)換非常消耗性能。

從內(nèi)存語義來說,加鎖的過程會清除工作內(nèi)存中的共享變量,再從主內(nèi)存讀取,而釋放鎖的過程則是將工作內(nèi)存中的共享變量寫回主內(nèi)存。

實(shí)際上大部分時(shí)候我認(rèn)為說到monitorenter就行了,但是為了更清楚的描述,還是再具體一點(diǎn)。

如果再深入到源碼來說,synchronized實(shí)際上有兩個(gè)隊(duì)列waitSet和entryList。

  1. 當(dāng)多個(gè)線程進(jìn)入同步代碼塊時(shí),首先進(jìn)入entryList
  2. 有一個(gè)線程獲取到monitor鎖后,就賦值給當(dāng)前線程,并且計(jì)數(shù)器+1
  3. 如果線程調(diào)用wait方法,將釋放鎖,當(dāng)前線程置為null,計(jì)數(shù)器-1,同時(shí)進(jìn)入waitSet等待被喚醒,調(diào)用notify或者notifyAll之后又會進(jìn)入entryList競爭鎖
  4. 如果線程執(zhí)行完畢,同樣釋放鎖,計(jì)數(shù)器-1,當(dāng)前線程置為null

圖片圖片

線程池了解嗎?有哪些常見參數(shù)?

線程池是為了減少頻繁的創(chuàng)建線程和銷毀線程帶來的性能損耗。線程池的構(gòu)造函數(shù)有7個(gè)參數(shù):

圖片圖片

  • corePoolSize:線程池核心線程數(shù)量。默認(rèn)情況下,線程池中線程的數(shù)量如果 <= corePoolSize,那么即使這些線程處于空閑狀態(tài),那也不會被銷毀。
  • maximumPoolSize:線程池中最多可容納的線程數(shù)量。當(dāng)一個(gè)新任務(wù)交給線程池,如果此時(shí)線程池中有空閑的線程,就會直接執(zhí)行,如果沒有空閑的線程且當(dāng)前線程池的線程數(shù)量小于corePoolSize,就會創(chuàng)建新的線程來執(zhí)行任務(wù),否則就會將該任務(wù)加入到阻塞隊(duì)列中,如果阻塞隊(duì)列滿了,就會創(chuàng)建一個(gè)新線程,從阻塞隊(duì)列頭部取出一個(gè)任務(wù)來執(zhí)行,并將新任務(wù)加入到阻塞隊(duì)列末尾。如果當(dāng)前線程池中線程的數(shù)量等于maximumPoolSize,就不會創(chuàng)建新線程,就會去執(zhí)行拒絕策略。
  • keepAliveTime:當(dāng)線程池中線程的數(shù)量大于corePoolSize,并且某個(gè)線程的空閑時(shí)間超過了keepAliveTime,那么這個(gè)線程就會被銷毀。
  • unit:就是keepAliveTime時(shí)間的單位。
  • workQueue:工作隊(duì)列。當(dāng)沒有空閑的線程執(zhí)行新任務(wù)時(shí),該任務(wù)就會被放入工作隊(duì)列中,等待執(zhí)行。
  • threadFactory:線程工廠??梢杂脕斫o線程取名字等等
  • handler:拒絕策略。當(dāng)一個(gè)新任務(wù)交給線程池,如果此時(shí)線程池中有空閑的線程,就會直接執(zhí)行,如果沒有空閑的線程,就會將該任務(wù)加入到阻塞隊(duì)列中,如果阻塞隊(duì)列滿了,就會創(chuàng)建一個(gè)新線程,從阻塞隊(duì)列頭部取出一個(gè)任務(wù)來執(zhí)行,并將新任務(wù)加入到阻塞隊(duì)列末尾。如果當(dāng)前線程池中線程的數(shù)量等于maximumPoolSize,就不會創(chuàng)建新線程,就會去執(zhí)行拒絕策略。

線程池工作隊(duì)列滿了有哪些拒接策略?

當(dāng)線程池的任務(wù)隊(duì)列滿了之后,線程池會執(zhí)行指定的拒絕策略來應(yīng)對,常用的四種拒絕策略包括:CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy,此外,還可以通過實(shí)現(xiàn)RejectedExecutionHandler接口來自定義拒絕策略。

四種預(yù)置的拒絕策略:

  • CallerRunsPolicy,使用線程池的調(diào)用者所在的線程去執(zhí)行被拒絕的任務(wù),除非線程池被停止或者線程池的任務(wù)隊(duì)列已有空缺。
  • AbortPolicy,直接拋出一個(gè)任務(wù)被線程池拒絕的異常。
  • DiscardPolicy,不做任何處理,靜默拒絕提交的任務(wù)。
  • DiscardOldestPolicy,拋棄最老的任務(wù),然后執(zhí)行該任務(wù)。
  • 自定義拒絕策略,通過實(shí)現(xiàn)接口可以自定義任務(wù)拒絕策略。

有線程池參數(shù)設(shè)置的經(jīng)驗(yàn)嗎?

  • CPU密集型:corePoolSize = CPU核數(shù) + 1
  • IO密集型:corePoolSize = CPU核數(shù) * 2

手撕算法

  • 合并k個(gè)有序鏈表(面試官說給我出個(gè)簡單題)
責(zé)任編輯:武曉燕 來源: 小林coding
相關(guān)推薦

2023-09-14 07:10:04

2018-10-22 17:52:28

GitHub代碼開發(fā)者

2013-01-08 09:40:16

大數(shù)據(jù)軟硬件技術(shù)

2023-12-18 08:44:54

Dragonfly基座引擎引擎框架

2017-05-11 11:40:43

2024-04-03 07:56:50

推薦系統(tǒng)多任務(wù)推薦

2019-01-23 13:04:09

QLCNAND閃存

2021-06-28 08:57:29

快手騰訊員工

2012-09-03 13:38:43

Ubuntu 12.1Wayland

2019-04-26 12:11:37

快手秒變閃電手

2021-10-12 06:40:02

cp 命令機(jī)械盤

2024-10-29 08:09:18

2014-05-22 10:05:12

Windows 8

2012-07-30 13:58:32

無線網(wǎng)絡(luò)

2019-05-31 12:03:06

SQLHadoop大數(shù)據(jù)

2022-07-08 09:26:45

Flink快手計(jì)算

2018-03-18 23:34:57

2021-08-10 15:32:12

Redis緩存數(shù)據(jù)庫

2020-12-16 08:11:21

服務(wù)supervisor進(jìn)程

2019-01-15 10:49:57

傳統(tǒng)存儲私有云塊存儲
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號