并發(fā)面試題
- 線程
操作系統(tǒng)能夠運(yùn)算調(diào)度的最小單位 被包含在進(jìn)程當(dāng)中 進(jìn)程運(yùn)行的實(shí)際最小單位 - 進(jìn)程與線程之間不同
線程是進(jìn)程的子集 不同的進(jìn)程使用不同的內(nèi)存空間 但是所有的線程共享一片相同的內(nèi)存空間(堆) - 線程的幾種狀態(tài)秋忙?
新建狀態(tài):new
就緒狀態(tài):start返回時(shí)處于就緒狀態(tài) 不一定立馬執(zhí)行run 可能需要競爭CPU
運(yùn)行狀態(tài):獲得CPU 執(zhí)行run
阻塞狀態(tài):線程沒有運(yùn)行結(jié)束 暫時(shí)讓出CPU
死亡狀態(tài):run方法正常退出跨算;異常 - Runnable還是Thread
如果需要繼承其他類 還是用Runnable - Thread中start和run的區(qū)別
start 內(nèi)部調(diào)用了run 但是會(huì)有新線程的啟動(dòng) run沒有新線程的啟動(dòng) - Runnable和Callable的區(qū)別
Callable的call方法可以返回值(裝載有Future的對象)和拋出異常 - Java內(nèi)存模型
如果兩個(gè)操作之間不遵循Happens-Before 那么JVM可以做任意的重排序(一般會(huì)做指令優(yōu)化重排) 多線程的情況下 如果不依照Happens-Before排序就會(huì)產(chǎn)生數(shù)據(jù)競爭問題 此時(shí)需要正確的同步- Volatile
只有成員變量才能使用 禁止指令重排可以保證下一個(gè)讀取操作可以在上一個(gè)寫操作之后完成(保證了一定的有序性)
- Volatile
- 什么是線程安全
多個(gè)線程訪問同一個(gè)類時(shí) 這個(gè)類都能表現(xiàn)正確的行為 - 什么是競態(tài)條件
當(dāng)一個(gè)運(yùn)行結(jié)果取決于多線程交替運(yùn)行時(shí)序 就會(huì)產(chǎn)生競態(tài)條件
最常見的類型是 先檢查后執(zhí)行 即通過一個(gè)可能失效的結(jié)果決定下一步的操作
無序處理 - 如何停止一個(gè)線程
線程運(yùn)行完會(huì)自動(dòng)退出
Volatile布爾變量取消任務(wù)中斷線程? - 線程發(fā)生異常
異常沒被捕獲 線程會(huì)停止執(zhí)行 Thread.UncaughtExceptionHandler處理 - 兩個(gè)線程共享數(shù)據(jù)
共享對象 阻塞隊(duì)列這種并發(fā)的數(shù)據(jù)結(jié)構(gòu) 偷霉? - notify notifyall區(qū)別
Notify在只有一個(gè)線程等待的時(shí)候才有用
notifyall 喚醒所有的線程并且允許它們爭奪鎖 確保至少有一個(gè)線程是活著的 - wait notify這些方法不定義在Thread中
Java提供的鎖是對象級的而不是線程級的 對象鎖能夠明顯的知道線程在等待哪個(gè)鎖 - ThreadLocal
ThreadLocal是保證線程安全的一種高效的辦法(空間換時(shí)間) 保存著線程以及其私有變量內(nèi)存副本拷貝的映射關(guān)系
怎么使得SimpleDateFormat變成線程安全的耀盗?
ThreadLocalRandom的實(shí)現(xiàn)原理励堡? - FutureTask
一個(gè)可以取消的異步運(yùn)算 只有當(dāng)運(yùn)算完成的時(shí)候結(jié)果才能取回 否則get方法會(huì)阻塞 使用實(shí)例翩隧? - Wait notify為什么需要在同步塊中妓布?
API的要求 為了防止產(chǎn)生競態(tài)條件 - 同步集合和并發(fā)集合的區(qū)別
并發(fā)集合的可擴(kuò)展性更高 比如像并發(fā)集合ConcurrentHashMap 不僅提供了線程安全 還有鎖分離 內(nèi)部分區(qū) - 堆和棧 區(qū)別
棧是線程私有的 堆是線程共享的
對象實(shí)例存在堆中 線程為了提高效率會(huì)弄一個(gè)緩存到自己的棧(工作內(nèi)存) 多線程下就會(huì)出現(xiàn)問題 volatitle就可以發(fā)揮作用 它要求線程從主存(堆)讀取變量的值
堆和棧道效率姻蚓? - 線程池
管理一組工作線程的資源池
三個(gè)好處:1?? 線程復(fù)用 2?? 提前創(chuàng)建線程提高響應(yīng)性 3?? 適當(dāng)?shù)恼{(diào)整線程池的大小 能夠避免多個(gè)線程搶占內(nèi)存耗盡內(nèi)存 - 如何解決生產(chǎn)者消費(fèi)者問題
BlockingQueue? - 避免死鎖
死鎖是指爭奪資源互相等待 避免死鎖的方法:阻止循環(huán)等待條件 將資源設(shè)置標(biāo)志位并且排序 規(guī)定每個(gè)進(jìn)程申請資源都必須按照一定的順序 - 死鎖 活鎖的區(qū)別
活鎖的線程狀態(tài)是不斷的改變的 兩個(gè)人同時(shí)給對方讓路 但是因?yàn)楸茏尩姆较蛞恢?導(dǎo)致不能繼續(xù)執(zhí)行 - 怎么檢測線程是否擁有鎖
Thread&holdsLock - synchronized和ReentrantLock的不同
ReetrantLock彌補(bǔ)了synchronized的局限性 :無法中斷正在等待的線程匣沼;無法無限的等待鎖
具有synchronized相同的互斥性和可見性
但是很危險(xiǎn) 它無法像synchronized自動(dòng)清除鎖 需要在finally中釋放鎖 項(xiàng)目中的應(yīng)用狰挡? - 三個(gè)線程T1 T2 T3 怎么確保按順序執(zhí)行?
使用join方法 在一個(gè)線程中啟動(dòng)另外一個(gè)線程 T3啟動(dòng)T2 T2啟動(dòng)T1 - yield作用
暫停正在執(zhí)行的線程對象 讓其他具有相同優(yōu)先級的線程執(zhí)行 并且放棄CPU 可能進(jìn)入到暫停狀態(tài)馬上又執(zhí)行
和sleep的區(qū)別释涛?
Sleep不考慮線程的優(yōu)先級加叁;sleep轉(zhuǎn)入阻塞狀態(tài)不會(huì)立馬執(zhí)行 - ConcurrentHashMap的并發(fā)度是什么
把實(shí)際的map劃分成若干部分來實(shí)現(xiàn)可擴(kuò)展性和線程安全 劃分依據(jù)并發(fā)度 默認(rèn)為16? - 提交任務(wù)時(shí)隊(duì)列已滿會(huì)發(fā)生什么唇撬?
RejectedExecutionException - 線程池的submit和execute的區(qū)別
都是向線程池提交任務(wù) execute返回類型時(shí)void submit返回類型時(shí)有計(jì)算結(jié)果的Futrue對象 - ReadWriteLock是什么它匕?
提升并發(fā)性能的鎖分離技術(shù) 維護(hù)一對關(guān)聯(lián)鎖 一個(gè)只讀一個(gè)只寫 沒有寫線程的情況下 一個(gè)讀鎖可能被多個(gè)讀線程持有 寫鎖是獨(dú)占的 ReentrantReadWriteLock來實(shí)現(xiàn)這個(gè)規(guī)則 - 同步塊內(nèi)線程拋出異常會(huì)發(fā)生什么?
會(huì)釋放鎖 - 創(chuàng)建線程安全的單例
枚舉