淺析Java多執行緒程式設計機制

azz發表於2007-08-23
淺析Java多執行緒程式設計機制[@more@]  多執行緒是Java語言的一大特性,多執行緒就是同時存在N個執行體,按幾條不同的執行線索共同工作的情況。程式,程式,執行緒,可以從不同的角度去理解。程式就是一段靜態的程式碼,可以理解成一組計算機命令的集合.進行就是這個程式一次動態的執行過程,從程式碼的載入到執行完畢的一個過程。執行緒是一個比程式小的單位,一個程式再執行的過程中可以產生多個執行緒,每個執行緒也是由生產到銷燬,可以理解成是進行的子集。我個人用一個覺得還算恰當的比喻來比喻三者。QQ客戶端就是一個程式,登陸一個QQ就是開始了這個程式的一個程式,再QQ上傳送訊息給好友就貌似這個程式中的一個執行緒。不知道這樣比喻恰當否?

  執行緒也是有狀態和宣告週期的,每個Java程式都會有一個預設的主執行緒,對於應用程式applcation來說main方法就是一個主執行緒.Java語言使用的是Thread類及其子類的物件來表示執行緒的.建立一個新的執行緒的生命週期如下狀態:

  1) 新建:當一個Thread類或者其子類的物件被宣告並建立時,新的執行緒物件處於新建狀態,此時它已經有了相應的記憶體空間和其他資源.
  2) 就緒:處於新建狀態的執行緒被啟動後,將進入執行緒佇列排隊等待CUP服務,這個時候具備了執行的條件,一旦輪到CPU的時候,就可以脫離建立它的主執行緒獨立開始自己的生命週期.
  3) 執行:就緒的執行緒被排程並獲得CUP的處理邊進入了執行狀態,每一個Thread類及其子類的物件都有一個重要的run()方法,當執行緒物件被排程執行的時候,它將自動呼叫本物件的run()方法,從第一句程式碼開始執行。所以說對執行緒的操作應該寫到run()方法中.
  4) 阻塞:一個正在執行的執行緒如果再某種情況下不能執行了.進入阻塞狀態,這個時候它不能進入排隊狀態,只有引起了阻塞的原因消失的時候,執行緒才可以繼續進入排隊狀態等待CUP處理。
  5) 死亡:處於死亡狀態的執行緒不具有繼續執行的能力,執行緒死亡主要的原因是正常執行的執行緒完成了全部工作,即執行完了run()方法,另外就是被提前強制的終止了。

  執行緒的排程也是有優先順序別的,就是說同樣的排列優先順序高可以提前被CPU處理,主要分三個級別,高中低.分別代表的數字是10.5.1分別有三個常量代表不可以被改變。最小優先順序的常量是MIN_PRIORITY,普通的優先順序的常量是NORM_PRIORITY,最高的優先順序的常量是MAX_PRIORITY一般主執行緒的優先順序是普通,另外可以透過Thread類的setPriority(int a)方法來修改系統自動設定的執行緒優先順序。

  Java中程式設計實現多執行緒應有兩種途徑,一種是建立自己的執行緒子類,另外是實現一個介面Runnable。無論是那種途徑最終讀需要使用Thread類及其方法。Thread類有兩種構造方法,public Thread()用來建立一個執行緒物件。public Thread(Runnable r)建立執行緒物件,引數r成為被建立的目標物件。這個目標必須實現Runnbale介面,給出該介面的run()方法的方法體,再方法體中操作.用兩個構造方法建立完的執行緒就是一個新建的狀態,等待處理.然後啟動執行緒的start()方法,啟動執行緒物件,執行緒進入排隊狀態也就是就緒狀態.然後執行緒操作run()方法這個方法裡的內容是被系統處理的內容.如果想使執行緒進入休眠狀態可以呼叫sleep()方法,可以給一個引數,代表休眠的毫秒.如果給兩個引數代表那秒。終止執行緒用yield()方法來完成.判斷執行緒是否銷燬可以用idAlive()方法判斷執行緒是否活著。Runnable介面只有一個方法run()方法,我們實現這個介面把要操作的程式碼寫到這個方法中,然後再把實現了整個介面的類的例項傳給Therad類的構造方法即可操作執行緒。

  執行緒同步是一個再處理執行緒的時候需要注意的問題,同步方法要用synchronized關鍵字類修飾,被這個關鍵字修飾後,當一個執行緒A使用這個方法後,其它執行緒想使用這個方法就必須等待,知道執行緒A使用完該方法後方可使用.下面我寫一個例子來說明執行緒同步,這個例子有兩個執行緒會計和出納,他們共同有一個賬本.他們倆都可以存取方法對賬本進行訪問,會計使用存取方法的時候寫入存錢的記錄,出納則寫入取錢的記錄。因此會計使用賬本的時候出納被禁止使用,反之也是如此。就是一個人使用另外一個人必須等待。下面我透過一個小程式Applet來實現這個事:

  import Java.applet.*;
  import Java.awt.*;
  import Java.awt.event.*;

  public class MyThread extends Applet implements Runnable {
  int money = 100;
  TextArea text1 = null;
  TextArea text2 = null;
  Thread Kuaiji = null;
  Thread Chuna = null;

  public void init() {
  Kuaiji = new Thread(this);
  Chuna = new Thread(this);
  text1 = new TextArea(20,8);
  text2 = new TextArea(20,8);
  add(text1);
  add(text2);
  }

  public void start() {
  Kuaiji.start();
  Chuna.start();
  }

  public synchronized void Cunqu(int number) {
  if(Thread.currentThread() == Kuaiji) {
   for(int i=1;i <=3;i++) {
    money = money + number;
    try {Thread.sleep(1000);}
    catch(Exception e){}
    text1.append(" "+money);
   }
  }
  else if(Thread.currentThread() == Chuna) {
   for(int i=1;i <=2;i++) {
    money = money - number/2;
    try {Thread.sleep(1000);}
    catch(Exception e){}
    text2.append(" "+money);
   }
  }
  }

  public void run() {
  if(Thread.currentThread()==Kuaiji || Thread.currentThread()==Chuna) {
   for(int i=1;i <=3;i++) {
    Cunqu(30);
   }
  }
  }
  }

  當一個執行緒使用同步方法中的某個變數,而此變數又需要其他執行緒修改後才能符合本執行緒的需要,那麼可以再同步方法中使用wait()方法,使本執行緒等待,並允許其他執行緒使用這個同步方法.用notfyAll()方法同志所有的由於使用這個同步方法的處於等待的執行緒結束等待進入同步方法中執行,如果使使用notfy()就是單獨同志一個執行緒進行同步方法進行活動.簡單的理解就是wait()方法讓執行緒等待,notfy()當一個執行緒執行,notfyAll()讓全部執行緒執行。雖然Java支援多執行緒.一般執行緒不需要我們自己處理.但是也是需要了解和掌握的。再日後的專案中獲取會根據不同情況,有不同的需求。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10901326/viewspace-965485/,如需轉載,請註明出處,否則將追究法律責任。

相關文章