Runnable是run() , Callable是call()。其中Runnable可以提交給..."/>
溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java基礎 (14) - 多線程

發(fā)布時間:2020-08-08 02:31:32 來源:網(wǎng)絡 閱讀:208 作者:lm8751 欄目:編程語言

1.實現(xiàn)多線程
Thread、Runnable、Callable、ExecutorService四種方式
Runnable和Callable的區(qū)別是
1>Runnable是run() , Callable是call()。其中Runnable可以提交給Thread來包裝下,Callable一般都是提交給ExecuteService和FutureTask來執(zhí)行。
2>Callable能返回值和拋出異常。
3>Callable獲取值時會導致所在的線程等待,直到get返回值為止,返回之前會中斷當前線程。
參考
四種實現(xiàn)多線程方式:https://blog.csdn.net/u011480603/article/details/75332435/
Callable、Future和FutureTask :https://www.cnblogs.com/dolphin0520/p/3949310.html

2.啟動線程
run() 和 start()區(qū)別
start()是真真的開啟一個線程執(zhí)行。(等待系統(tǒng)分配cpu資源)
run()只是線程的一個普通方法,只調(diào)用run(),該方法會在調(diào)用者線程進行。(不會在新線程執(zhí)行)

3.停止線程
(1)使用退出標志(volatile 布爾變量),也就是當run方法完成后線程終止。
(2)使用interrupted方法阻塞線程(修改線程中斷標記值) ,isInterrupted()返回線程標記值。
(3)使用stop方法強行終止線程 (這個方法不推薦使用,因為stop和suspend、resume一樣,也可能發(fā)生不可預料的結果)

4.線程異常
線程出現(xiàn)異常結果
(1)線程運行 ->線程處理了異?;驋伋?br/>(2)線程停止 ->發(fā)生異常線程沒有捕獲或沒有將其拋出,此時JVM會使用Thread.getUncaughtExceptionHandler()來查詢線程的UncaughtExceptionHandler并將線程和異常作為參數(shù)傳遞給handler的uncaughtException()方法進行處理
使用步驟
第一步:implements UncaughtExceptionHandler 自定義異常處理類
第二步:Thread t = new Thread(new ExceptionThread());
t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
t.start();

5.線程同步
synchronized方法、synchronized模塊(wait/notify機制)、ReenreantLock、volatile、while輪詢等方式
(1)synchronized方法
由于java的每個對象都有一個內(nèi)置鎖,當用此關鍵字修飾方法時,?
內(nèi)置鎖會保護整個方法。在調(diào)用該方法前,需要獲得內(nèi)置鎖,否則就處于阻塞狀態(tài)

(2)synchronized模塊 - wait/notify機制
同步是一種高開銷的操作,因此應該盡量減少同步的內(nèi)容
通常沒有必要同步整個方法,使用synchronized代碼塊同步關鍵代碼即可

(3)? ReenreantLock
JavaSE1.5.新增了一個java.util.concurrent包來支持同步。??ReentrantLock類是可重入、互斥、實現(xiàn)了Lock接口的鎖,??它與使用synchronized方法和快具有相同的基本行為和語義,并且擴展了其能力?ReenreantLock類的常用方法有:
??????? ReentrantLock() : 創(chuàng)建一個ReentrantLock實例????????? lock() : 獲得鎖????????? unlock() : 釋放鎖? - finally 中執(zhí)行
從上可看出 他在寫法上相對synchronized 更簡潔

(4) volatile
可見性 - 使用volatile修飾域相當于告訴虛擬機該域可能會被其他線程更新.因此每次使用該域就要重新計算,而不是使用寄存器中的值
有序性 - java優(yōu)化的時候 ,將不改變此修飾過的變量執(zhí)行順序

6.如何避免死鎖?
Java多線程中的死鎖 死鎖是指兩個或兩個以上的進程在執(zhí)行過程中,因爭奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,它們都將無法推進下去。這是一個嚴重的問題,因為死鎖會讓你的程序掛起無法完成任務,死鎖的發(fā)生必須滿足以下四個條件:

  • 互斥條件:一個資源每次只能被一個進程使用。
  • 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
  • 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
  • 循環(huán)等待條件:若干進程之間形成一種頭尾相接的循環(huán)等待資源關系。
    解決死鎖
    https://www.cnblogs.com/android-blogs/p/5765148.html

7.常見問題
(1)wait/notify機制
以生產(chǎn)者和消費者為例
調(diào)用任意方法,必須在對象鎖方法體中
生產(chǎn)者調(diào)用notify后,生產(chǎn)者所在線程并不會立即退出線程,得等到生產(chǎn)者執(zhí)行完畢。消費者才有可能機會執(zhí)行
消費者被喚醒后是從wait()方法(被阻塞的地方)后面執(zhí)行,而不是重新從同步塊開頭
(2)notify和notifyAll有什么區(qū)別
notify()方法不能喚醒某個具體的線程,所以只有一個線程在等待的時候它才有用武之地。
notifyAll()喚醒所有線程并允許他們爭奪鎖確保了至少有一個線程能繼續(xù)運行
(3)wait() 和 sleep()有什么不同?
sleep()方法僅僅釋放CPU資源或者讓當前線程停止執(zhí)行一段時間,但不會釋放鎖
釋放鎖資源,進入資源等待池等待
參考:https://www.cnblogs.com/hapjin/p/5492619.html
(4)Synchronized和ReentrantLock的區(qū)別
ReentrantLock是類,那么它就提供了比synchronized更多更靈活的特性,可以被繼承、可以有方法、可以有各種各樣的類變量,ReentrantLock比synchronized的擴展性體現(xiàn)在幾點上:
(1)ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖
(2)ReentrantLock可以獲取各種鎖的信息
(3)ReentrantLock可以靈活地實現(xiàn)多路通知
另外,二者的鎖機制其實也是不一樣的。ReentrantLock底層調(diào)用的是Unsafe的park方法加鎖,synchronized操作的應該是對象頭中mark word

參考:https://blog.csdn.net/qq_41212104/article/details/81773717

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI