1. 程式人生 > >java執行緒學習總結

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介面的實現類。

             
執行緒裡的常用方法:

start()   run()  currentThread()  getName()  setName(String name) yield() join()  sleep() isAlive() 
                 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.生產者、消費者的例子