1.實現多線程
Thread、Runnable、Callable、ExecutorService四種方式
Runnable和Callable的區別是
1>Runnable是run() , Callable是call()。其中Runnable能夠提交給Thread來包裝下,Callable通常都是提交給ExecuteService和FutureTask來執行。
2>Callable能返回值和拋出異常。
3>Callable獲取值時會致使所在的線程等待,直到get返回值爲止,返回以前會中斷當前線程。
參考
四種實現多線程方式:https://blog.csdn.net/u011480603/article/details/75332435/
Callable、Future和FutureTask :http://www.javashuo.com/article/p-nbqerguk-bp.htmlhtml
2.啓動線程
run() 和 start()區別
start()是真真的開啓一個線程執行。(等待系統分配cpu資源)
run()只是線程的一個普通方法,只調用run(),該方法會在調用者線程進行。(不會在新線程執行)java
3.中止線程
(1)使用退出標誌(volatile 布爾變量),也就是當run方法完成後線程終止。
(2)使用interrupted方法阻塞線程(修改線程中斷標記值) ,isInterrupted()返回線程標記值。
(3)使用stop方法強行終止線程 (這個方法不推薦使用,由於stop和suspend、resume同樣,也可能發生不可預料的結果)android
4.線程異常
線程出現異常結果
(1)線程運行 ->線程處理了異常或拋出
(2)線程中止 ->發生異常線程沒有捕獲或沒有將其拋出,此時JVM會使用Thread.getUncaughtExceptionHandler()來查詢線程的UncaughtExceptionHandler並將線程和異常做爲參數傳遞給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的每一個對象都有一個內置鎖,當用此關鍵字修飾方法時,
內置鎖會保護整個方法。在調用該方法前,須要得到內置鎖,不然就處於阻塞狀態ide
(2)synchronized模塊 - wait/notify機制
同步是一種高開銷的操做,所以應該儘可能減小同步的內容
一般沒有必要同步整個方法,使用synchronized代碼塊同步關鍵代碼便可優化
(3) ReenreantLock
JavaSE1.5.新增了一個java.util.concurrent包來支持同步。
ReentrantLock類是可重入、互斥、實現了Lock接口的鎖,
它與使用synchronized方法和快具備相同的基本行爲和語義,而且擴展了其能力
ReenreantLock類的經常使用方法有:
ReentrantLock() : 建立一個ReentrantLock實例
lock() : 得到鎖
unlock() : 釋放鎖 - finally 中執行
從上可看出 他在寫法上相對synchronized 更簡潔.net
(4) volatile
可見性 - 使用volatile修飾域至關於告訴虛擬機該域可能會被其餘線程更新.所以每次使用該域就要從新計算,而不是使用寄存器中的值
有序性 - java優化的時候 ,將不改變此修飾過的變量執行順序線程
6.如何避免死鎖?
Java多線程中的死鎖 死鎖是指兩個或兩個以上的進程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。這是一個嚴重的問題,由於死鎖會讓你的程序掛起沒法完成任務,死鎖的發生必須知足如下四個條件:htm
7.常見問題
(1)wait/notify機制
以生產者和消費者爲例
調用任意方法,必須在對象鎖方法體中
生產者調用notify後,生產者所在線程並不會當即退出線程,得等到生產者執行完畢。消費者纔有可能機會執行
消費者被喚醒後是從wait()方法(被阻塞的地方)後面執行,而不是從新從同步塊開頭
(2)notify和notifyAll有什麼區別
notify()方法不能喚醒某個具體的線程,因此只有一個線程在等待的時候它纔有用武之地。
notifyAll()喚醒全部線程並容許他們爭奪鎖確保了至少有一個線程能繼續運行
(3)wait() 和 sleep()有什麼不一樣?
sleep()方法僅僅釋放CPU資源或者讓當前線程中止執行一段時間,但不會釋放鎖
釋放鎖資源,進入資源等待池等待
參考:http://www.javashuo.com/article/p-kenmdcfj-kk.html
(4)Synchronized和ReentrantLock的區別
ReentrantLock是類,那麼它就提供了比synchronized更多更靈活的特性,能夠被繼承、能夠有方法、能夠有各類各樣的類變量,ReentrantLock比synchronized的擴展性體如今幾點上:
(1)ReentrantLock能夠對獲取鎖的等待時間進行設置,這樣就避免了死鎖
(2)ReentrantLock能夠獲取各類鎖的信息
(3)ReentrantLock能夠靈活地實現多路通知
另外,兩者的鎖機制其實也是不同的。ReentrantLock底層調用的是Unsafe的park方法加鎖,synchronized操做的應該是對象頭中mark word對象