Java 多線程編程Java給多線程編程提供了內(nèi)置的支持,。一個(gè)多線程程序包含兩個(gè)或多個(gè)能并發(fā)運(yùn)行的部分。程序的每一部分都稱作一個(gè)線程,,并且每個(gè)線程定義了一個(gè)獨(dú)立的執(zhí)行路徑,。 多線程是多任務(wù)的一種特別的形式,。多線程比多任務(wù)需要更小的開銷,。 這里定義和線程相關(guān)的另一個(gè)術(shù)語:進(jìn)程:一個(gè)進(jìn)程包括由操作系統(tǒng)分配的內(nèi)存空間,包含一個(gè)或多個(gè)線程,。一個(gè)線程不能獨(dú)立的存在,,它必須是進(jìn)程的一部分。一個(gè)進(jìn)程一直運(yùn)行,,直到所有的非守候線程都結(jié)束運(yùn)行后才能結(jié)束,。 多線程能滿足程序員編寫非常有效率的程序來達(dá)到充分利用CPU的目的,因?yàn)镃PU的空閑時(shí)間能夠保持在最低限度,。 一個(gè)線程的生命周線程經(jīng)過其生命周期的各個(gè)階段。下圖顯示了一個(gè)線程完整的生命周期,。
線程的優(yōu)先級每一個(gè)Java線程都有一個(gè)優(yōu)先級,,這樣有助于操作系統(tǒng)確定線程的調(diào)度順序,。Java優(yōu)先級在MIN_PRIORITY(1)和MAX_PRIORITY(10)之間的范圍內(nèi)。默認(rèn)情況下,,每一個(gè)線程都會(huì)分配一個(gè)優(yōu)先級NORM_PRIORITY(5),。 具有較高優(yōu)先級的線程對程序更重要,并且應(yīng)該在低優(yōu)先級的線程之前分配處理器時(shí)間,。然而,,線程優(yōu)先級不能保證線程執(zhí)行的順序,而且非常依賴于平臺(tái),。 創(chuàng)建一個(gè)線程Java提供了兩種創(chuàng)建線程方法:
通過實(shí)現(xiàn)Runnable接口來創(chuàng)建線程創(chuàng)建一個(gè)線程,,最簡單的方法是創(chuàng)建一個(gè)實(shí)現(xiàn)Runnable接口的類,。 為了實(shí)現(xiàn)Runnable,,一個(gè)類只需要執(zhí)行一個(gè)方法調(diào)用run(),聲明如下: publicvoid run() 你可以重寫該方法,,重要的是理解的run()可以調(diào)用其他方法,,使用其他類,并聲明變量,,就像主線程一樣,。 在創(chuàng)建一個(gè)實(shí)現(xiàn)Runnable接口的類之后,你可以在類中實(shí)例化一個(gè)線程對象,。 Thread定義了幾個(gè)構(gòu)造方法,,下面的這個(gè)是我們經(jīng)常使用的: Thread(Runnable threadOb,String threadName); 這里,threadOb 是一個(gè)實(shí)現(xiàn)Runnable 接口的類的實(shí)例,,并且 threadName指定新線程的名字,。 新線程創(chuàng)建之后,你調(diào)用它的start()方法它才會(huì)運(yùn)行,。 void start(); 實(shí)例下面是一個(gè)創(chuàng)建線程并開始讓它執(zhí)行的實(shí)例: // 創(chuàng)建一個(gè)新的線程 class NewThread implements Runnable { Thread t; NewThread() { // 創(chuàng)建第二個(gè)新線程 t = new Thread(this, "Demo Thread"); System.out.println("Child thread: " + t); t.start(); // 開始線程 } // 第二個(gè)線程入口 public void run() { try { for(int i = 5; i > 0; i--) { System.out.println("Child Thread: " + i); // 暫停線程 Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Child interrupted."); } System.out.println("Exiting child thread."); } } public class ThreadDemo { public static void main(String args[]) { new NewThread(); // 創(chuàng)建一個(gè)新線程 try { for(int i = 5; i > 0; i--) { System.out.println("Main Thread: " + i); Thread.sleep(100); } } catch (InterruptedException e) { System.out.println("Main thread interrupted."); } System.out.println("Main thread exiting."); } } 編譯以上程序運(yùn)行結(jié)果如下: Child thread: Thread[Demo Thread,5,main] Main Thread: 5 Child Thread: 5 Child Thread: 4 Main Thread: 4 Child Thread: 3 Child Thread: 2 Main Thread: 3 Child Thread: 1 Exiting child thread. Main Thread: 2 Main Thread: 1 Main thread exiting. 通過繼承Thread來創(chuàng)建線程創(chuàng)建一個(gè)線程的第二種方法是創(chuàng)建一個(gè)新的類,,該類繼承Thread類,然后創(chuàng)建一個(gè)該類的實(shí)例,。 繼承類必須重寫run()方法,,該方法是新線程的入口點(diǎn)。它也必須調(diào)用start()方法才能執(zhí)行,。 實(shí)例
|
序號 | 方法描述 |
---|---|
1 | public void start()使該線程開始執(zhí)行,;Java 虛擬機(jī)調(diào)用該線程的 run 方法。 |
2 | public void run() 如果該線程是使用獨(dú)立的 Runnable 運(yùn)行對象構(gòu)造的,,則調(diào)用該 Runnable 對象的 run 方法,;否則,該方法不執(zhí)行任何操作并返回,。 |
3 | public final void setName(String name) 改變線程名稱,,使之與參數(shù) name 相同。 |
4 | public final void setPriority(int priority) 更改線程的優(yōu)先級,。 |
5 | public final void setDaemon(boolean on) 將該線程標(biāo)記為守護(hù)線程或用戶線程,。 |
6 | public final void join(long millisec) 等待該線程終止的時(shí)間最長為 millis 毫秒。 |
7 | public void interrupt() 中斷線程,。 |
8 | public final boolean isAlive() 測試線程是否處于活動(dòng)狀態(tài),。 |
測試線程是否處于活動(dòng)狀態(tài)。 上述方法是被Thread對象調(diào)用的,。下面的方法是Thread類的靜態(tài)方法,。
序號 | 方法描述 |
---|---|
1 | public static void yield() 暫停當(dāng)前正在執(zhí)行的線程對象,并執(zhí)行其他線程。 |
2 | public static void sleep(long millisec) 在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),,此操作受到系統(tǒng)計(jì)時(shí)器和調(diào)度程序精度和準(zhǔn)確性的影響,。 |
3 | public static boolean holdsLock(Object x) 當(dāng)且僅當(dāng)當(dāng)前線程在指定的對象上保持監(jiān)視器鎖時(shí),才返回 true,。 |
4 | public static Thread currentThread() 返回對當(dāng)前正在執(zhí)行的線程對象的引用,。 |
5 | public static void dumpStack() 將當(dāng)前線程的堆棧跟蹤打印至標(biāo)準(zhǔn)錯(cuò)誤流。 |
如下的ThreadClassDemo 程序演示了Thread類的一些方法:
// 文件名 : DisplayMessage.java // 通過實(shí)現(xiàn) Runnable 接口創(chuàng)建線程 public class DisplayMessage implements Runnable { private String message; public DisplayMessage(String message) { this.message = message; } public void run() { while(true) { System.out.println(message); } } }
// 文件名 : GuessANumber.java // 通過繼承 Thread 類創(chuàng)建線程 public class GuessANumber extends Thread { private int number; public GuessANumber(int number) { this.number = number; } public void run() { int counter = 0; int guess = 0; do { guess = (int) (Math.random() * 100 + 1); System.out.println(this.getName() + " guesses " + guess); counter++; }while(guess != number); System.out.println("** Correct! " + this.getName() + " in " + counter + " guesses.**"); } }
// 文件名 : ThreadClassDemo.java public class ThreadClassDemo { public static void main(String [] args) { Runnable hello = new DisplayMessage("Hello"); Thread thread1 = new Thread(hello); thread1.setDaemon(true); thread1.setName("hello"); System.out.println("Starting hello thread..."); thread1.start(); Runnable bye = new DisplayMessage("Goodbye"); Thread thread2 = new Thread(hello); thread2.setPriority(Thread.MIN_PRIORITY); thread2.setDaemon(true); System.out.println("Starting goodbye thread..."); thread2.start(); System.out.println("Starting thread3..."); Thread thread3 = new GuessANumber(27); thread3.start(); try { thread3.join(); }catch(InterruptedException e) { System.out.println("Thread interrupted."); } System.out.println("Starting thread4..."); Thread thread4 = new GuessANumber(75); thread4.start(); System.out.println("main() is ending..."); } }
運(yùn)行結(jié)果如下,,每一次運(yùn)行的結(jié)果都不一樣,。
Starting hello thread... Starting goodbye thread... Hello Hello Hello Hello Hello Hello Hello Hello Hello Thread-2 guesses 27 Hello ** Correct! Thread-2 in 102 guesses.** Hello Starting thread4... Hello Hello ..........remaining result produced.
在多線程編程時(shí),你需要了解以下幾個(gè)概念:
有效利用多線程的關(guān)鍵是理解程序是并發(fā)執(zhí)行而不是串行執(zhí)行的,。例如:程序中有兩個(gè)子系統(tǒng)需要并發(fā)執(zhí)行,這時(shí)候就需要利用多線程編程,。
通過對多線程的使用,,可以編寫出非常高效的程序。不過請注意,,如果你創(chuàng)建太多的線程,程序執(zhí)行的效率實(shí)際上是降低了,,而不是提升了,。
請記住,上下文的切換開銷也很重要,,如果你創(chuàng)建了太多的線程,,CPU花費(fèi)在上下文的切換的時(shí)間將多于執(zhí)行程序的時(shí)間!
|