多線程是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.awt.TextArea;
public class ThreadDemo extends Applet implements Runnable {
int j = 1;
int money = 100;
TextArea ta1 = null;
TextArea ta2 = null;
Thread kuaiJi = null;
Thread chuNa = null;
public void init() {
kuaiJi = new Thread(this);
chuNa = new Thread(this);
ta1 = new TextArea(20, 8);
ta2 = new TextArea(20, 8);
add(ta1);
add(ta2);
}
public void start() {
kuaiJi.start();
chuNa.start();
}
public synchronized void cunQu(int n) {
j += 1;
if(Thread.currentThread() == kuaiJi) {
ta1.append(" " + "No." + j);
for (int i = 0; i< 3; i++) {
money += n;
try {
Thread.sleep(1000);
} catch (Exception e){}
ta1.append(" " + money);
}
} else if (Thread.currentThread() == chuNa) {
ta2.append(" " + "No." + j);
for(int i = 0; i < 3; i++) {
money -= n;
try {
Thread.sleep(1000);
} catch (Exception e){}
ta2.append(" " + money);
}
}
}
public void run() {
// TODO Auto-generated method stub
if (Thread.currentThread() == kuaiJi || Thread.currentThread() == chuNa) {
for (int i = 1; i <= 300; i++) {
this.cunQu(20);
}
}
}
}
當一個線程使用同步方法中的某個變量,而此變量又需要其他線程修改後才能符合本線程的需要,那麼可以再同步方法中使用wait()方法,使本線程等待,並 允許其他線程使用這個同步方法。用notfyAll()方法同志所有的由於使用這個同步方法的處於等待的線程結束等待進入同步方法中運行,如果使使用 notfy()就是單獨同志一個線程進行同步方法進行活動。簡單的理解就是wait()方法讓線程等待,notfy()當一個線程運行,notfyAll ()讓全部線程運行。雖然Java支持多線程。一般線程不需要我們自己處理。但是也是需要了解和掌握的。再日後的項目中獲取會根據不同情況,有不同的需 求。