Java-进阶:多线程2
生活随笔
收集整理的這篇文章主要介紹了
Java-进阶:多线程2
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
目錄
一、Lock 接口
二、線程間的通信
三、線程池
四、定時(shí)器 Timer
五、多線程和異常
一、Lock 接口
1. 線程鎖
- 鎖是控制多個(gè)線程對共享資源進(jìn)行訪問的工具。通常,鎖提供了對共享資源的獨(dú)占訪問。一次只能有一個(gè)線程獲得鎖,對共享資源的所有訪問都需要首先獲得鎖
- Lock比Synchronize更為靈活的功能:
- boolean tryLock()僅在調(diào)用時(shí)鎖為空閑狀態(tài)才獲取該鎖。如果鎖可用,則獲取鎖,并立即返回值 true。如果鎖不可用,則此方法將立即返回值 false。
2. 同步弊端
- 影響效率
- 如果出現(xiàn)了嵌套鎖,容易產(chǎn)生死鎖
3. 死鎖
- 死鎖:死鎖是指兩個(gè)以上的線程在執(zhí)行過程中,因?yàn)闋帄Z資源而產(chǎn)生的一種相互等待的現(xiàn)象
二、線程間的通信
1. wait()
- 導(dǎo)致當(dāng)前線程處于等待狀態(tài)
- 只有在其他線程線程中調(diào)用了notify()方法或 notifyAll()來喚醒,因?yàn)?wait()方法阻塞了線程
- 在調(diào)用 wait方法之前,當(dāng)前線程必須擁有此對象監(jiān)視器(鎖對象),換句話說,必須在 鎖對象 上調(diào)用 wait方法(此方法只應(yīng)該由作為此對象監(jiān)視器的所有者的線程 來調(diào)用)
- 一旦在鎖對象上調(diào)用了 wait方法,緊接著:
- 當(dāng)前線程放棄 cpu 執(zhí)行權(quán),并等待
- 放棄持有的 鎖對象
wait()和 sleep()比較
相同點(diǎn):使當(dāng)前線程放棄cpu執(zhí)行權(quán),處于阻塞狀態(tài)
不同點(diǎn):
2. nofity()
- 喚醒在此對象(調(diào)用wait的同一個(gè)鎖對象) 監(jiān)視器上等待的單個(gè)線程;如果所有線程都在此對象上等待,則會選擇喚醒其中一個(gè)線程
- 直到當(dāng)前線程放棄此對象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程
- 被喚醒的線程將以常規(guī)方式與在該對象上主動同步的其他所有線程進(jìn)行競爭
3. notifyAll()
- 喚醒在此對象監(jiān)視器上等待的所有線程
三、線程池
1. 概述
- 我們創(chuàng)建一個(gè)線程,只能使用一次
- 線程池,其實(shí)就是一個(gè)容納多個(gè)線程的容器,其中的線程可以反復(fù)使用,省去了頻繁創(chuàng)建線程對象的操作,無需反復(fù)創(chuàng)建線程而消耗過多資源
- 線程池的原理:線程池里每一個(gè)線程代碼結(jié)束后,并不會死亡,而是再次回到線程池中成為空閑狀態(tài),等待下一次被使用
為什么要使用線程池?
2. 創(chuàng)建線程池
- 通常,線程池都是通過 線程池工廠 創(chuàng)建,再調(diào)用線程池中的方法獲取線程,再通過線程去執(zhí)行任務(wù)方法Executors:線程池創(chuàng)建工廠類
- public static ExecutorService newCachedThreadPool()
- 創(chuàng)建一個(gè)可根據(jù)需要?jiǎng)?chuàng)建新線程 的線程池,但是在以前構(gòu)造的線程可用時(shí)將重用它們 (可變)
- 對于執(zhí)行很多短期異步(短但是頻繁) 任務(wù)的程序而言,這些線程池通常可提高程序性能
- 如果現(xiàn)有線程沒有可用的,則創(chuàng)建一個(gè)新線程并添加到池中
- 終止并從緩存中移除那些已有 60 秒鐘未被使用的線程(折中)
- public static ExecutorService newFixedThreadPool(int nThreads)
- 創(chuàng)建一個(gè)可重用固定線程數(shù)的線程池,以共享的無界隊(duì)列方式來運(yùn)行這些線程
- 如果在所有線程處于活動狀態(tài)時(shí)提交附加任務(wù),則在有可用線程之前,附加任務(wù)將在隊(duì)列中等待
- public static ExecutorService newSingleThreadExecutor()
- 創(chuàng)建一個(gè)使用單個(gè) worker 線程的 Executor,以無界隊(duì)列方式來運(yùn)行該線程
- 可保證順序地執(zhí)行各個(gè)任務(wù)
- 以上方法返回了一個(gè)ExecutorService,該對象表示一個(gè)線程池,它可以執(zhí)行 Runable對象代表的線程。
3. 提交任務(wù)
- Runnable 接口
- Callable 接口類似于 Runnable,用來指定線程的任務(wù)。其中的 call() 方法,用來返回線程任務(wù)執(zhí)行完畢后的結(jié)果,call方法可拋出異常。
- ExecutorService:線程池類
- <T> Future<T> **submit**(Callable<T> task):獲取線程池中的某一個(gè)線程對象,并執(zhí)行線程中的call()方法
- Future接口:用來記錄線程任務(wù)執(zhí)行完畢后產(chǎn)生的結(jié)果。
- get()獲取 Future對象中封裝的數(shù)據(jù)結(jié)果
- void shutdown():啟動一次順序關(guān)閉,執(zhí)行以前提交的任務(wù),但 不接受新任務(wù)
- shutdownNow()方法: 試圖停止所有正在執(zhí)行的活動任務(wù),暫停處理正在等待的任務(wù),并返回等待執(zhí)行的任務(wù)列表。
4. 使用線程池中線程對象的步驟:
- 創(chuàng)建線程池對象
- 創(chuàng)建 Runnable 接口/Callable接口 子類對象
- 提交 Runnable 接口/Callable接口 子類對象
- 關(guān)閉線程池
四、定時(shí)器 Timer
1. 概述
- 調(diào)度定時(shí)任務(wù),幫助我們在稍后的時(shí)刻執(zhí)行定時(shí)任務(wù)。一種工具,線程用其安排以后在后臺線程中執(zhí)行的任務(wù)。可安排任務(wù) 執(zhí)行一次,或者 定期重復(fù)執(zhí)行
2. TimerTask 定時(shí)任務(wù)
- 定時(shí)任務(wù):TimerTask對象表示定時(shí)任務(wù)
- Timer調(diào)度定時(shí)任務(wù),定時(shí)任務(wù)的內(nèi)容由TimerTask的run方法 運(yùn)行決定
- 在 timer 中所有的定時(shí)任務(wù)都是運(yùn)行在同一個(gè)線程中
- 如果利用TimerTask的cancel要取消定時(shí)任務(wù),在定時(shí)任務(wù)已經(jīng)開始運(yùn)行時(shí), 調(diào)用cancel方法,是沒有效果的
利用Timer的cancel方法取消定時(shí)任務(wù),其實(shí)是終止Timer本身
五、多線程和異常
- 在 Thread 類中,不可以拋出編譯型異常,但是可以拋出運(yùn)行時(shí)異常
- 當(dāng) 運(yùn)行時(shí)異常拋出線程(溢出線程),能不能捕獲?
java語言,并不能直接用try-catch代碼塊捕獲,溢出線程的異常,這是java語言實(shí)現(xiàn)上的一個(gè)遺憾,但是,并不是說,溢出線程的異常開發(fā)者就沒辦法捕獲了。—> Thread.UncaughtExceptionHandler
- static setDefaultUncaughtExceptionHandler,處理所有線程中未捕獲的異常(溢出線程的異常)
- setUncaughtExceptionHandler,處理某一個(gè)線程中的未捕獲的異常(溢出線程的異常)
總結(jié)
以上是生活随笔為你收集整理的Java-进阶:多线程2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黄体功能不全做试管
- 下一篇: 二面蚂蚁金服(交叉面),已拿offer,