更新時間:2019-08-18 09:00:00 來源:動力節(jié)點 瀏覽2855次
實現(xiàn)多線程方式有三種:
1、繼承Thread 復寫run方法 無返回值
2、實現(xiàn)Runnable接口復寫run方法,調(diào)用thread類的start開啟 無返回值
3、實現(xiàn)callable(指定泛型類)接口實現(xiàn)call方法,創(chuàng)建FutureTask類傳入callable實例,創(chuàng)建thread類傳入futureTask實例調(diào)用start方法開啟 有返回值
Thread與runnable關(guān)系
發(fā)現(xiàn)在多線程實現(xiàn)過程中有三種做法,thread類 runnable接口,從代碼結(jié)構(gòu)本身來講使用runnable是最方便的,因為其可以避免單繼承的局限,用時也可以更好的進行功能的擴充。
thread類是runnable接口的字類,thread類子類實際復寫的是runnable接口的run方法,
runnable與callable的區(qū)別?
1、runnable是JDK1.0的時候提出的多線程實現(xiàn)接口,而callable是JDK1.5之后提出的。
2、Runnable接口之中提供一個run方法,沒有返回值。
callable接口提供call方法,可以有返回值
想要實現(xiàn)多線程啟動,使用thread的start方法 從古不變
多線程狀態(tài):
對于多線程開發(fā)而言,編寫程序的過程之中總是按照,定義線程主體類,而后通過thread類進行調(diào)用start,線程就已經(jīng)開始運行了,因為整體的線程處理有自己的一套運行的狀態(tài):
創(chuàng)建-start開啟-就緒-阻塞-運行狀態(tài)-終止。
1、任何一個線程的對象都應該使用thread類進行封裝,所以線程的啟動使用的是start,進入到就緒狀態(tài)并沒有執(zhí)行,
2、進入到就緒狀態(tài)后,就需要等待進行資源調(diào)度,當某一個程序調(diào)度成功后則進度到運行狀態(tài)run方法,但是所有的線程不可能一致持續(xù)執(zhí)行下去,中間需要產(chǎn)生一些暫停的狀態(tài),列入:某線程執(zhí)行一段時間之后就需要讓出資源,而后這個線程就進入阻塞狀態(tài),隨后重新回到就緒狀態(tài)
3、當run方法執(zhí)行完畢后,實際上該線程的主要任務也就結(jié)束了,那么此時就進入到停止狀態(tài)
start準備執(zhí)行--》就緒狀態(tài)--》運行狀態(tài)-》結(jié)束
多線程的主要操作方法都在thread類中定義的
線程的命名與的取:
多線程的運行狀態(tài)是不確定的,那么在程序的開發(fā)之中為了可以獲取到一些只能夠依靠線程的名字來進行操作
所以線程的名字是一個只管蟲咬的概念,這樣在thread類中就提供線程名稱的處理方式,構(gòu)造方法傳遞名字,設置名字的方法,獲取名字的方法。
對于線程對象的獲取,是不可能依靠一個this來完成的,因為線程的狀態(tài)不可控制,但是有一點可以明確,所有的線程對象一點要執(zhí)行run方法,那么這個時候我們可以考慮獲取當前線程,在thread里面提供獲取當前線程的方法,
線程休眠:
如果說現(xiàn)在希望某線程可以暫緩執(zhí)行一次,那么久可以使用休眠處理,在thread類中定義的休眠方法如下,
sleep方法
休眠有可能被打斷,一定要處理
休眠時間一到程序會立即恢復執(zhí)行
休眠的主要特點是可以自動實現(xiàn)線程的喚醒,以繼續(xù)進行后續(xù)的處理,但是需要注意的是,如果現(xiàn)在有多個線程對象,那么休眠也有先后順序的
此時產(chǎn)生五個線程對象,并且這五個現(xiàn)場對象執(zhí)行的方法體是相同的,此時從我們程序執(zhí)行的感覺來講好像是若干個線程一起進行休眠后,又一起喚醒執(zhí)行,其實不是,線程是隨機搶占Cpu資源,誰先搶到誰先執(zhí)行。
線程中斷:
在之前發(fā)現(xiàn)線程的休眠里面提供有一個中斷異常,實際上久證明線程的休眠是可以被打斷的,而這種打斷肯定是由其他線程完成的。
在這個thread類里面提供又中斷執(zhí)行的處理方法
1、isInterrupted 是否被中斷
2、interrupt 中斷線程
所有正在執(zhí)行的線程都是可以中斷的,中斷線程必須進行異常處理
線程的同步與死鎖:
在多線程的處理之中,可以利用runnable描述多線程操作的資源,而thread描述每一個線程對象,于是當多個線程訪問同一資源的時候如果處理不當就會產(chǎn)生數(shù)據(jù)的錯誤操作。
方法同步關(guān)鍵字 :synchronized 同步代碼塊,同步方法兩種實現(xiàn)方式
線程的強制執(zhí)行:
所謂的線程的強制執(zhí)行指的是當滿足某些條件后,某一個線程對象講可以一致獨占資源,一直到該線程的程序執(zhí)行結(jié)束,
線程禮讓:
線程的禮讓指先講線程的執(zhí)行權(quán)讓給別的線程先執(zhí)行,讓出執(zhí)行權(quán) 方y(tǒng)ield方法
禮讓執(zhí)行的時候,每次都會禮讓當前資源
線程優(yōu)先級:
從理論上來講線程的優(yōu)先級越高最先搶到CPU執(zhí)行權(quán)的幾率越高,在thread類里賣弄針對優(yōu)先級有兩種處理方式
1、設置優(yōu)先級
2、獲取優(yōu)先級
在進行優(yōu)先級定義的時候都是通過int類型的數(shù)字來完成的,而對于此數(shù)字的選擇在thread類里面久定義號了常量
最高優(yōu)先級MAX_PRIORITY 10
中級 NORM 5
低級 MAIN 1
所有線程默認優(yōu)先級是中級
線程同步:
經(jīng)過分析之后已經(jīng)可以確認同步問題鎖產(chǎn)生的主要問題,那么下面就需要進行同步問題的解決,但是解決同步問題的關(guān)鍵是鎖。
指的是當某一個線程執(zhí)行操作的時候,其他線程只能在外面等待。
如果要想程序之中實現(xiàn)這把鎖的功能,需要使用關(guān)鍵字synchronized關(guān)鍵字來實現(xiàn),同步代碼塊,在同步代碼塊的操作里面代碼只允許一個線程執(zhí)行,
1、利用同步代碼塊處理:
一般要進行永不對象處理的時候采用當前對象this進行同步
加入同步處理之后,程序的整體性能能下降了,同步實際上會造成性能的降低
2、利用同步方法解決,只需要在方法定義上使用synchronization關(guān)鍵字修飾即可
在Java原生類庫的時候會發(fā)現(xiàn),系統(tǒng)中許多的類上使用的同步處理采用的都是同步方法,但是千萬記住同步會造成性能下降
死鎖的概念:
死鎖是在進行多線程同步處理之中有可能產(chǎn)生的一種問題。
所謂的死鎖指的是若干個線程彼此互相等待的狀態(tài)。
在多線程開發(fā)過程之中最為著名的案例就是生產(chǎn)者與消費者的操作,操作流程如下
1、生產(chǎn)者負責內(nèi)容的生產(chǎn)
2、每當生產(chǎn)者生產(chǎn)完成一項完整的內(nèi)容之后消費者要從這里取走內(nèi)容
3、如果生產(chǎn)者沒有生產(chǎn)完成則消費者需要等待他生產(chǎn)完成才能消費,如果消費者還沒有對內(nèi)容進行消費,生產(chǎn)者需要等待消費者 消費完成之后在進行生產(chǎn)
解決數(shù)據(jù)同步問題:
如果要解決問題,首先解決的就是數(shù)據(jù)同步的處理問題,如果要想解決數(shù)據(jù)同步最簡單的方式就是同步代碼塊或者同步方法。
但是同步不能解決數(shù)據(jù)重復問題,只能保證執(zhí)行順序是一個一個的執(zhí)行并不會并發(fā)處理
解決方案是線程等待與喚醒機制
如果說現(xiàn)在想要解決生產(chǎn)者與消費者的問題,那么最好的解決方案就是使用等待與喚醒機制,而對于等待與喚醒機制主要依賴的是object類的方法處理
方法1:wait 等待
方法2: notify 喚醒
方法3:notifyAll 喚醒全部
優(yōu)雅的停止線程:
在多線程操作之中如果要啟動多線程肯定是使用thread類的start方法,而如果對于多線程需要進行停止處理,thread類原本提供有stop方法,但是stop方法在1.2的時候已經(jīng)被廢除了,也不將建議在代碼中使用stop方法。
stop destroysuspend resume這些方法1.2都被廢除了 不建議使用
想要實現(xiàn)多線程停止需要通過一種柔和的方式進行處理,自定義屬性進行判斷修改
線程守護:
現(xiàn)在假設有一個人并且這個人有一個保鏢,這個保鏢一定是在這個人活著的時候進行守護的,如果這個人已經(jīng)死了額,保鏢也就沒有作用了,
所以在多線程里面進行守護線程的定義,也就是說如果現(xiàn)在主線程的程序或者其他線程還在執(zhí)行的時候,那么外面的守護線程就一直存在,并且允許在后臺狀態(tài),
setDaemon true 就是設置守護線程方法。
isDaemon 是否是守護線程
可以發(fā)現(xiàn)所有的守護線程都是圍繞用戶線程執(zhí)行的,如果用戶線程執(zhí)行完畢,守護線程也就消失了,在JVM里面最大的守護線程就是GC線程,程序執(zhí)行中GC線程會一直存在,如果程序執(zhí)行完畢,GC線程也就消失
volatile直接內(nèi)存操作:
面試題:請解釋volatile與synchronized的區(qū)別?
volatile主要在屬性上使用,而synchronized是在代碼塊與方法上使用的
volatile無法描述同步處理,它只是一種直接內(nèi)存的處理,避免了副本的操作,而synchronized是實現(xiàn)同步操作的
volatile它可以更快的表示變量的修改和處理