1、線程池的7個參數(shù)的關(guān)系拍霜,jdk自帶的線程池有哪些嘱丢,拒絕策略有哪些
核心線程數(shù)、最大線程數(shù)祠饺、workqueue越驻、非核心線程存活時間、timeunit道偷、飽和拒絕策略缀旁、線程工廠
4種拒絕策略:
直接拋異常(默認)、交給調(diào)用者執(zhí)行试疙、直接discard诵棵、discard最早未處理的線程
2抠蚣、使用線程池提交任務(wù)后怎么獲取返回結(jié)果祝旷,CountDownLatch的使用
ExecutorService接口中有以下方法,返回值是Future:返回值Future也是一個接口,通過他可以獲得任務(wù)執(zhí)行的返回值怀跛。
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
返回結(jié)果是異步的距贷,但是如果調(diào)用Future.get()方法時線程還沒有執(zhí)行完,會阻塞
public interface Future<V> {?
? ? boolean cancel(boolean mayInterruptIfRunning);?
? ? boolean isCancelled();?
? ? boolean isDone();?
? ? V get() throws InterruptedException, ExecutionException;?
? ? V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;?
}
countDownLatch:
CountDownLatch?的作用就是 允許 count 個線程阻塞在一個地方吻谋,直至所有線程的任務(wù)都執(zhí)行完畢忠蝗。
關(guān)于FutureTask:https://blog.csdn.net/ThinkWon/article/details/102542404
3、項目中使用了哪種線程池漓拾,有沒有遇到什么坑阁最,關(guān)鍵參數(shù)是怎么確定的
4、當(dāng)一個線程池里的線程異常后會發(fā)生什么
1)execute方法執(zhí)行時骇两,會拋出(打印)堆棧異常速种。
? ? ? submit方法執(zhí)行時,返回結(jié)果封裝在future中低千,如果調(diào)用future.get()方法則必須進行異常捕獲配阵,從而可以拋出(打印)堆棧異常
2)線程池中一個線程異常了后,不影響其他線程任務(wù)
3)線程池會把這個線程移除掉示血,并創(chuàng)建一個新的線程放到線程池中棋傍。
關(guān)于異常捕獲:
1)線程池中線程中異常盡量手動捕獲
2)通過設(shè)置ThreadFactory的UncaughtExceptionHandler可以對未捕獲的異常做保底處理,通過execute提交任務(wù)难审,線程依然會中斷瘫拣,而通過submit提交任務(wù),可以獲取線程執(zhí)行結(jié)果告喊,線程異常會在get執(zhí)行結(jié)果時拋出拂铡。
5、synchronized
同步方法調(diào)用指令讀取運行時常量池中方法的 ACC_SYNCHRONIZED 標(biāo)志來隱式實現(xiàn)的
代碼塊是由 monitorenter 和 monitorexit 指令來實現(xiàn)同步的
ObjectMonitor中有兩個隊列葱绒,_WaitSet 和 _EntryList感帅,用來保存ObjectWaiter對象列表( 每個等待鎖的線程都會被封裝成ObjectWaiter對象),_owner指向持有ObjectMonitor對象的線程地淀。
1)當(dāng)多個線程同時訪問一段同步代碼時失球,首先會進入 _EntryList 集合。
2)當(dāng)線程獲取到對象的monitor 后進入 _Owner 區(qū)域并把monitor中的owner變量設(shè)置為當(dāng)前線程同時monitor中的計數(shù)器count加1帮毁。
3)若線程調(diào)用 wait() 方法实苞,將釋放當(dāng)前持有的monitor,owner變量恢復(fù)為null烈疚,count自減1黔牵,同時該線程進入 WaitSet集合中等待被喚醒。
4)若線程被喚醒重新獲取對象monitor后進入_Owner 區(qū)域并把monitor中的owner變量設(shè)置為當(dāng)前線程同時monitor中的計數(shù)器count加1爷肝。
5)若當(dāng)前線程執(zhí)行完畢也將釋放monitor(鎖)并復(fù)位變量的值猾浦,以便其他線程進入獲取monitor(鎖)陆错。
6)對CAS的理解以及存在的問題
7、線程的狀態(tài)以及如何轉(zhuǎn)換
https://zhuanlan.zhihu.com/p/130875882
New(新創(chuàng)建)金赦、Runnable(可運行)音瓷、Blocked(被阻塞)、Waiting(等待)夹抗、Timed Waiting(計時等待)绳慎、Terminated(被終止)
8、鎖升級過程詳解
https://www.cnblogs.com/mingyueyy/p/13054296.html? (好帖)
偏向鎖01(無鎖為001漠烧,偏向鎖為101杏愤,前一位表示當(dāng)前是無鎖還是偏向鎖)、自旋鎖00已脓、重量級鎖11声邦,
synchronized的執(zhí)行過程:
1)檢測Mark Word里面是不是當(dāng)前線程的ID,如果是摆舟,表示當(dāng)前線程處于偏向鎖
2)如果不是亥曹,則使用CAS將當(dāng)前線程的ID替換Mard Word,如果成功則表示當(dāng)前線程獲得偏向鎖恨诱,置偏向標(biāo)志位1
3)如果失敗媳瞪,則說明發(fā)生競爭,撤銷偏向鎖照宝,進而升級為輕量級鎖蛇受。
4)當(dāng)前線程使用CAS將對象頭的Mark Word替換為鎖記錄指針,如果成功厕鹃,當(dāng)前線程獲得鎖
5)如果失敗兢仰,表示其他線程競爭鎖,當(dāng)前線程便嘗試使用自旋來獲取鎖剂碴。
6)如果自旋成功則依然處于輕量級狀態(tài)把将。
7)如果自旋失敗(默認10次)或者當(dāng)前自旋線程數(shù)超過了cpu總線程的一半忆矛,則升級為重量級鎖察蹲。
9、ThreadLocal的實現(xiàn)原理催训、存在的問題洽议,InheritableThreadLocal如何使用以及存在的問題
Thread?類中有一個?threadLocals?和 一個?inheritableThreadLocals?變量,它們都是?ThreadLocalMap?類型的變量,我們可以把?ThreadLocalMap?理解為ThreadLocal?類實現(xiàn)的定制化的?HashMap漫拭。默認情況下這兩個變量都是 null亚兄,只有當(dāng)前線程調(diào)用?ThreadLocal?類的?set或get方法時才創(chuàng)建它們,實際上調(diào)用這兩個方法的時候采驻,我們調(diào)用的是ThreadLocalMap類對應(yīng)的?get()审胚、set()方法匈勋。
內(nèi)存泄漏問題:ThreadLocalMap?中使用的 key 為?ThreadLocal?的弱引用,而 value 是強引用。所以菲盾,如果?ThreadLocal?沒有被外部強引用的情況下颓影,在垃圾回收的時候各淀,key 會被清理掉懒鉴,而 value 不會被清理掉。這樣一來碎浇,ThreadLocalMap?中就會出現(xiàn) key 為 null 的 Entry临谱。假如我們不做任何措施的話,value 永遠無法被 GC 回收奴璃,這個時候就可能會產(chǎn)生內(nèi)存泄露悉默。ThreadLocalMap 實現(xiàn)中已經(jīng)考慮了這種情況,在調(diào)用?set()苟穆、get()抄课、remove()?方法的時候,會清理掉 key 為 null 的記錄雳旅。使用完?ThreadLocal方法后 最好手動調(diào)用remove()方法
InheritableThreadLocal:
在thread的init方法內(nèi)判斷有無父線程跟磨,且父線程的InheritableThreadLocal是否為空,不為空則將父線程的InheritableThreadLocal傳遞給子線程
問題:
線程池中的線程是反復(fù)使用的攒盈,可能發(fā)生value串位問題
如果需要解決這個問題抵拘,可以自定義一個RunTask類,使用反射加代理的方式來實現(xiàn)業(yè)務(wù)主線程存放在InheritableThreadLocal中值的間接復(fù)制型豁。
10僵蛛、如何確定線程池大小
https://blog.csdn.net/yudianxiaoxiao/article/details/115134748
如果是CPU密集型任務(wù),就需要盡量壓榨CPU迎变,參考值可以設(shè)為?Ncpu+1
如果是IO密集型任務(wù)充尉,參考值可以設(shè)置為 2 *?Ncpu
Ncpu = CPU的數(shù)量
Ucpu = 目標(biāo)CPU的使用率, 0 <= Ucpu <= 1
W/C = 等待時間與計算時間的比率
Nthreads = Ncpu x Ucpu x (1 + W/C)
11衣形、樂觀鎖喉酌、悲觀鎖使用場景
樂觀鎖(ABA問題):版本號或時間戳控制,適用于多讀少寫的場景
悲觀鎖:DB的行鎖泵喘、表鎖等泪电,適用于數(shù)據(jù)一致性比較高的場景
12、自旋鎖
自旋鎖(spinlock):是指當(dāng)一個線程在獲取鎖的時候纪铺,如果鎖已經(jīng)被其它線程獲取相速,那么該線程將循環(huán)等待,然后不斷的判斷鎖是否能夠被成功獲取鲜锚,直到獲取到鎖才會退出循環(huán)突诬。
獲取鎖的線程一直處于活躍狀態(tài)苫拍,但是并沒有執(zhí)行任何有效的任務(wù),使用這種鎖會造成busy-waiting旺隙。
自旋鎖如果持有鎖的時間太長绒极,則會導(dǎo)致其它等待獲取鎖的線程耗盡CPU。
13蔬捷、volatile關(guān)鍵字詳解
https://www.cnblogs.com/ustc-anmin/p/11434769.html
可見性垄提、有序性,不能保證原子性