java執行緒學習總結
1.理解程式、程序、執行緒的概念
- 程式可以理解為靜態的程式碼
- 程序可以理解為執行中的程式。
- 執行緒可以理解為程序的進一步細分,程式的一條執行路徑
2.如何建立java程式的執行緒(重點)
方式一:繼承於Thread類
class PrintNum extends Thread{ public void run(){ //子執行緒執行的程式碼 for(int i = 1;i <= 100;i++){ if(i % 2 == 0){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } public PrintNum(String name){ super(name); } } public class TestThread { public static void main(String[] args) { PrintNum p1 = new PrintNum("執行緒1"); PrintNum p2 = new PrintNum("執行緒2"); p1.setPriority(Thread.MAX_PRIORITY);//10 p2.setPriority(Thread.MIN_PRIORITY);//1 p1.start(); p2.start(); } }
方式二:實現Runnable介面
class SubThread implements Runnable{ public void run(){ //子執行緒執行的程式碼 for(int i = 1;i <= 100;i++){ if(i % 2 == 0){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } } public class TestThread{ public static void main(String[] args){ SubThread s = new SubThread(); Thread t1 = new Thread(s); Thread t2 = new Thread(s); t1.setName("執行緒1"); t2.setName("執行緒2"); t1.start(); t2.start(); } }
兩種方式的對比:聯絡:class Thread implements Runnable比較哪個好?
- 實現的方式較好。
- ①解決了單繼承的侷限性。
- ②如果多個執行緒有共享資料的話,建議使用實現方式,同時,共享資料所在的類可以作為Runnable介面的實現類。
執行緒裡的常用方法:
getPriority() setPriority(int i); wait() notify() notifyAll()
3.執行緒的生命週期
4.執行緒的同步機制(重點、難點)
前提:如果我們建立的多個執行緒,存在著共享資料,那麼就有可能出現執行緒的安全問題:當其中一個執行緒操作共享資料時,還未操作完成, 另外的執行緒就參與進來,導致對共享資料的操作出現問題。
解決方式:要求一個執行緒操作共享資料時,只有當其完成操作完成共享資料,其它執行緒才有機會執行共享資料。
方式一:同步程式碼塊:
synchronized(同步監視器){
//操作共享資料的程式碼
}
注:1.同步監視器:俗稱鎖,任何一個類的物件都可以才充當鎖。要想保證執行緒的安全,必須要求所有的執行緒共用同一把鎖!
2.使用實現Runnable介面的方式建立多執行緒的話,同步程式碼塊中的鎖,可以考慮是this。如果使用繼承Thread類的方式,慎用this!
3.共享資料:多個執行緒需要共同操作的變數。 明確哪部分是操作共享資料的程式碼。
方式二:同步方法:將操作共享資料的方法宣告為synchronized。
比如:public synchronized void show(){ //操作共享資料的程式碼}
注:1.對於非靜態的方法而言,使用同步的話,預設鎖為:this。如果使用在繼承的方式實現多執行緒的話,慎用!
2.對於靜態的方法,如果使用同步,預設的鎖為:當前類本身。以單例的懶漢式為例。 Class clazz = Singleton.class
總結:釋放鎖:wait();
不釋放鎖: sleep() yield() suspend() (過時,可能導致死鎖)
死鎖:不同的執行緒分別佔用對方需要的同步資源不放棄,都在等待對方放棄自己需要的同步資源,就形成了執行緒的死鎖
死鎖是我們在使用同步時,需要避免的問題!
5.執行緒的通訊:如下的三個方法必須使用在同步程式碼塊或同步方法中!
wait():當在同步中,執行到此方法,則此執行緒“等待”,直至其他執行緒執行notify()的方法,將其喚醒,喚醒後繼續其wait()後的程式碼
notify()/notifyAll():在同步中,執行到此方法,則喚醒其他的某一個或所有的被wait的執行緒。
>例題:1.兩個執行緒交替列印1-100自然數 2.生產者、消費者的例子