Java語言入門 -- 第七章 Java的多線程

第七章 Java的多線程

          

7.1 多 線 程 的 概 念

多 線 程 編 程 的 含 義 是 你 可 將 程 序 任 務 分 成 幾 個 並 行 的子 任 務。 特 別 是 在 網 絡 編 程 中, 你 會 發 現 很 多 功 能 是 可 以並 發 執 行 的。 比 如 網 絡 傳 輸 速 度 較 慢, 用 戶 輸 入 速 度 較 慢,你 可 以 用 兩 個 獨 立 的 線 程 去 完 成 這 ?copy; 功 能, 而 不 影 響正 常 的 顯 示 或 其 他 功 能。 多 線 程 是 與 單 線 程 比 較 而 言 的,普 通 的WINDOWS採 用 單 線 程 程 序 結 構, 其 工 作 原 理 是: 主 程 序有 一 個 消 息 循 環, 不 斷 從 消 息 隊 列 中 讀 入 消 息 來 決 定 下一 步 所 要 幹 的 事 情, 一 般 是 一 個 子 函 數, 只 有 等 這 個 子 函數 執 行 完 返 回 後, 主 程 序 才 能 接 收 另 外 的 消 息 來 執 行。 比如 子 函 數 功 能 是 在 讀 一 個 網 絡 數 據, 或 讀 一 個 文 件, 只 有等 讀 完 這 ?copy; 數 據 或 文 件 才 能 接 收 下 一 個 消 息。 在 執 行這 個 子 函 數 過 程 中 你 什 麼 也 不 能 幹。 但 往 往 讀 網 絡 數 據和 等 待 用 戶 輸 入 有 很 多 時 間 處 於 等 待 狀 態, 多 線 程 利 用這 個 特 點 將 任 務 分 成 多 個 並 發 任 務 後, 就 可 以 解 決 這 個問 題。

7.1.1 Java線 程 的 模 型

Java的 設 計 思 想 是 建 立 在 當 前 大 多 數 操 作 系 統 都 實 現 了線 程 調 度。Java虛 擬 機 的 很 多 任 務 都 依 賴 線 程 調 度, 而 且 所有 的 類 庫 都 是 爲 多 線 程 設 計 的。 實 時 上,Java支 持Macintosh和Ms-dos 的 平 臺 ?reg; 所 以 遲 遲 未 出 來 就 是 因 爲 這 兩 個 平 臺 都 不 支持 多 線 程。Java利 用 多 線 程 實 現 了 整 個 執 行 環 境 是 異 步 的。在Java程 序 裏 沒 有 主 消 息 循 環。 如 果 一 個 線 程 等 待 讀 取 網絡 數 據, 它 可 以 運 行 但 不 停 止 系 統 的 其 他 線 程 執 行。 用 於處 理 用 戶 輸 入 的 線 程 大 多 時 間 是 等 待 用 戶 敲 鍵 盤 或 擊 鼠標。 你 還 可 以 使 動 畫 的 每 一 幀 ?reg; 間 停 頓 一 秒 而 並 不 使系 統 暫 停。 一 ?copy; 線 程 啓 動 後, 它 可 以 被 掛 起, 暫 時 不讓 它 執 行。 掛 起 的 線 程 可 以 重 新 恢 復 執 行。 任 何 時 間 線 程都 可 以 被 停 止, 被 停 止 的 線 程 就 不 能 再 重 新 啓 動。 Java語言 裏, 線 程 表 現 爲 線 程 類, 線 程 類 封 裝 了 所 有 需 要 的 線 程操 作 控 制。 在 你 心 裏, 必 須 很 清 晰 地 區 分 開 線 程 對 象 和 運行 線 程, 你 可 以 將 線 程 對 象 看 作 是 運 行 線 程 的 控 制 面 板。在 線 程 對 象 裏 有 很 多 函 數 來 控 制 一 個 線 程 是 否 運 行, 睡眠, 掛 起 或 停 止。 線 程 類 是 控 制 線 程 行 爲 的 唯 一 的 手 段。一 ?copy; 一 個Java程 序 啓 動 後, 就 已 經 有 一 個 線 程 在 運 行。你 可 通 過 調 用Thread.currentThread 函 數 來 查 看 當 前 運 行 的 是哪 一 個 線 程。 一 ?copy; 你 得 到 一 個 線 程 的 控 制 柄, 你 就 可以 作 一 ?copy; 很 有 趣 的 事 情, 即 使 單 線 程 也 一 樣。 下 面 這個 例 子 讓 你 知 道 怎 樣 操 縱 當 前 線 程。 Filename:testthread

class testthread { public static void main(String args[]) { Thread t =Thread.currentThread(); t.setName("This Thread is running"); System.out.println("The running thread:" + t); try { for (int i=0;i<5;i++) { System.out.println("Sleep time "+i); Thread.sleep(1000); }

} catch (InterruptedException e) {System.out.println("thread has wrong"); }

} }

執 行 結 果:java testthread The running thread:Thread[This Thread is running,5,main] Sleep time 0 Sleep time 1 Sleep time 2 Sleep time 3 Sleep time 4

7.1.2 啓 動 接 口

一 個 線 程 並 不 激 動 人 心, 多 個 線 程 才 有 實 際 意 義。 我 們怎 樣 創 建 更 多 的 線 程 呢? 我 們 需 要 創 建 線 程 類 的 另 一 個實 例。 當 我 們 構 造 了 線 程 類 的 一 個 新 的 實 例, 我 們 必 須 告訴 它 在 新 的 線 程 裏 應 執 行 哪 一 段 程 序。 你 可 以 在 任 意 實現 了 啓 動 接 口 的 對 象 上 啓 動 一 個 線 程。 啓 動 接 口 是 一 個抽 象 接 口, 來 表 示 本 對 象 有 一 ?copy; 函 數 想 異 步 執 行。 要實 現 啓 動 接 口, 一 個 類 只 需 要 有 一 個 叫run的 函 數。 下 面 是創 建 一 個 新 線 程 的 例 子:

Filename:twothread.java

class twothread implements Runnable { twothread() { Thread t1 =Thread.currentThread(); t1.setName("The first main thread"); System.out.println("The running thread:" + t1); Thread t2 = new Thread(this,"the second thread"); System.out.println("creat another thread"); t2.start(); try { System.out.println("first thread will sleep"); Thread.sleep(3000); }catch (InterruptedException e) {System.out.println("first thread has wrong"); } System.out.println("first thread exit"); } public void run() { try { for (int i=0;i<5;i++) { System.out.println("Sleep time for thread 2:"+i); Thread.sleep(1000); }

} catch (InterruptedException e) {System.out.println("thread has wrong"); }

System.out.println("second thread exit"); } public static void main(String args[]) { new twothread(); } }

執 行 結 果:java twothread

The running thread:Thread[The first main thread,5,main] creat another thread first thread will sleep Sleep time for thread 2:0 Sleep time for thread 2:1 Sleep time for thread 2:2 first thread exit Sleep time for thread 2:3 Sleep time for thread 2:4 second thread exit

main線 程 用new Thread(this, "the second thread")創 建 了一 個Thread對 象, 通 過 傳 遞 第 一 個 參 數 來 標 明 新 線 程 來 調 用this對象 的run函 數。 然 後 我 們 調 用start函 數, 它 將 使 線 程 從run函 數開 始 執 行。

7.1.3 同 步

因 爲 多 線 程 給 你 提 ?copy; 了 程 序 的 異 步 執 行 的 功 能, 所以 在 必 要 時 必 須 還 提 ?copy; 一 種 同 步 機 制。 例 如, 你 想 兩個 線 程 通 訊 並 共 享 一 個 復 雜 的 數 據 結 構, 你 需 要 一 種 機制 讓 他 們 相 互 牽 制 並 正 確 執 行。 爲 這 個 目 的,Java用 一 種 叫監 視 器(monitor)的 機 制 實 現 了 進 程 間 的 異 步 執 行。 可 以 將 監視 器 看 作 是 一 個 很 小 的 盒 子, 它 只 能 容 納 一 個 線 程。 一 ?copy; 一 個 線 程 進 入 一 個 監 視 器, 所 有 其 他 線 程 必 須 等 到 第 一個 線 程 退 出 監 視 器 後 才 能 進 入。 這 ?copy; 監 視 器 可 以 設 計成 保 護 共 享 的 數 據 不 被 多 個 線 程 同 時 操 作。 大 多 數 多 線程 系 統 將 這 ?copy; 監 視 器 設 計 成 對 象,Java提 ?copy; 了 一 種更 清 晰 的 解 決 方 案。 沒 有Monitor類; 每 個 對 象 通 過 將 他 們 的成 員 函 數 定 義 成synchronized來 定 義 自 己 的 顯 式 監 視 器, 一 ?copy; 一 個 線 程 執 行 在 一 個synchronized函 數 裏, 其 他 任 何 線 程 都 不能 調 用 同 一 個 對 象 的 synchronized函 數。

7.1.4 消 息

一 ?copy; 你 的 程 序 被 分 成 幾 個 邏 輯 線 程, 你 必 須 清 晰 的知 道 這 ?copy; 線 程 ?reg; 間 應 怎 樣 相 互 通 訊。Java 提 ?copy; 了wait和notify等 功 能 來 使 線 程 ?reg; 間 相 互 交 談。 一 個 線 程可 以 進 入 某 一 個 對 象 的synchronized 函 數 進 入 等 待 狀 態, 直到 其 他 線 程 顯 式 地 將 它 喚 醒。 可 以 有 多 個 線 程 進 入 同 一個 函 數 並 等 待 同 一 個 喚 醒 消 息。

7.2 Java線 程 例 子

7.2.1 顯 式 定 義 線 程

在 我 們 的 單 線 程 應 用 程 序 裏, 我 們 並 沒 有 看 見 線 程, 因爲Java能 自 動 創 建 和 控 制 你 的 線 程。 如 果 你 使 用 了 理 解Java語言 的 瀏 覽 器, 你 就 已 經 看 到 使 用 多 線 程 的Java程 序 了。 你 也許 注 意 到 兩 個 小 程 序 可 以 同 時 運 行, 或 在 你 移 動 滾 動 條時 小 程 序 繼 續 執 行。 這 並 不 是 表 明 小 程 序 是 多 線 程 的, 但說 明 這 個 瀏 覽 器 是 多 線 程 的。 多 線 程 應 用 程 序(或applet)可以 使 用 好 幾 個 執 行 上 下 文 來 完 成 它 們 的 工 作。 多 線 程 利用 了 很 多 任 務 包 含 單 獨 的 可 分 離 的 子 任 務 的 特 點。 每 一個 線 程 完 成 一 個 子 任 務。

但 是, 每 一 個 線 程 完 成 子 任 務 時 還 是 順 序 執 行 的。 一 個多 線 程 程 序 允 許 各 個 線 程儘快 執 行 完 它 們。 這 種 特 點 會 有更 好 的 實 時 輸 入 反 應。

7.2.2 多 線 程 例 子

下 面 這 個 例 子 創 建 了 三 個 單 獨 的 線 程, 它 們 分 別 打 印自 己 的“Hello World":

//Define our simple threads.They will pause for a short time //and then print out their names and delay times class TestThread extends Thread { private String whoami; private int delay;

//Our constructor to store the name (whoami) //and time to sleep (delay) public TestThread(String s, int d) { whoami = s; delay = d; }

//Run - the thread method similar to main() //When run is finished, the thread dies. //Run is called from the start() method of Thread public void run() { //Try to sleep for the specified time try { sleep(delay); } catch(InterruptedException e) {} //Now print out our name System.out.println("Hello World!"+whoami+""+delay); } } /** * Multimtest. A simple multithread thest program */ public class multitest { public static void main(String args[]) { TestThread t1,t2,t3; //Create our test threads t1 = new TestThread("Thread1",(int)(Math.readom()*2000)); t2 = new TestThread("Thread2",(int)(Math.readom()*2000)); t3 = new TestThread("Thread3",(int)(Math.readom()*2000));

//Start each of the threads t1.start(); t2.start(); t3.start(); } }

7.2.3 啓 動 一 個 線 程

程 序 啓 動 時 總 是 調 用main()函 數, 因 此main()是 我 們 創 建 和啓 動 線 程 的 地 方:

t1 = new TestThread("Thread1",(int)(Math.readom()*2000));

這 一 行 創 建 了 一 個 新 的 線 程。 後 面 的 兩 個 參 數 傳 遞 了線 程 的 名 稱 和 線 程 在 打 印 信 息 ?reg; 前 的 延 時 時 間。 因 爲我 們 直 接 控 制 線 程, 我 們 必 須 直 接 啓 動 它: t1.start();

7.2.4 操 作 線 程

如 果 創 建 線 程 正 常,t1應 包 含 一 個 有 效 的 執 行 線 程。 我們 在 線 程 的run()函 數 裏 控 制 線 程。 一 ?copy; 我 們 進 入run()函數, 我 們 便 可 執 行 裏 面 的 任 何 程 序。run()好 象main()一 樣。 一 ?copy;run() 執 行 完, 這 個 線 程 也 就 結 束 了。 在 這 個 例 子 裏,我 們 試 着 延 遲 一 個 隨 機 的 時 間(通 過 參 數 傳 遞?copy;: sleep(delay);

sleep()函 數 只 是 簡 單 地 告 訴 線 程 休 息 多 少 個 毫 秒 時 間。如 果 你 想 推 遲 一 個 線 程 的 執 行, 你 應 使 用sleep()函 數。 當 線程 睡 眠 是sleep()並 不 佔 用 系 統 資 源。 其 它 線 程 可 繼 續 工 作。一 ?copy; 延 遲 時 間 完 畢, 它 將 打 印"Hello World"和 線程 名 稱 及 延 遲 時 間。

7.2.5 暫 停 一 個 線 程

我 們 經 常 需 要 掛 起 一 個 線 程 而 不 指 定 多 少 時 間。 例 如,如 果 你 創 建 了 一 個 含 有 動 畫 線 程 的 小 程 序。 也 許 你 讓 用戶 暫 停 動 畫 至 到 他 們 想 恢 復 爲 止。 你 並 不 想 將 動 畫 線 程仍 調, 但 想 讓 它 停 止。 象 這 種 類 似 的 線 程 你 可 用suspend()函數 來 控 制: t1.suspend();

這 個 函 數 並 不 永 久 地 停 止 了 線 程, 你 還 可 用resume()函 數重 新 激 活 線 程: t1.resume();

7.2.6 停 止 一 個 線 程

線 程 的 最 後 一 個 控 制 是 停 止 函 數stop()。 我 們 用 它 來 停止 線 程 的 執 行: t1.stop();

注 意: 這 並 沒 有 消 滅 這 個 線 程, 但 它 停 止 了 線 程 的 執 行。並 且 這 個 線 程 不 能 用t1.start()重 新 啓 動。 在 我 們 的 例 子 裏,我 們 從 來 不 用 顯 式 地 停 止 一 個 線 程。 我 們 只 簡 單 地 讓 它執 行 完 而 已。 很 多 復 雜 的 線 程 例 子 將 需 要 我 們 控 制 每 一個 線 程。 在 這 種 情 況 下 會 使 用 到stop()函 數。 如 果 需 要, 你可 以 測 試 你 的 線 程 是 否 被 激 活。 一 個 線 程 已 經 啓 動 而 且沒 有 停 止 被 認 爲 是 激 活 的。 t1.isAlive() 如 果t1是 激 活 的, 這個 函 數 將 返 回true.

7.2.7 動 畫 例 子

下 面 是 一 個 包 含 動 畫 線 程 的applet例 子:

import java.awt.*; import java.awt.image.ImageProducer; import java.applet.Applet;

public class atest3 extends Applet implements Runnable { Image images[]; MediaTracker tracker; int index = 0; Thread animator;

int maxWidth,maxHeight; //Our off-screen components for double buffering. Image offScrImage; Graphics offScrGC;

//Can we paint yes? boolean loaded = false;

//Initialize the applet. Set our size and load the images public void init() [ //Set up our image monitor tracker = new MediaTracker(this);

//Set the size and width of our applet maxWidth = 100; maxHeight =100;

images = new Image[10]; //Set up the double-buffer and resize our applet try { offScrImage = createImage(maxWidth,maxHeight); offScrGC = offScrImage.getGraphics(); offScrGC.setColor(Color.lightGray); offScrGC.fillRect(0,0,maxWidth,maxHeight); resize(maxWidth,maxHeight); }catch (Exception e) { e.printStackTrace(); }

//load the animation images into an array for (int i=0;i<10;i++) { String imageFile = new String ("images/Duke/T" +String.valueOf(i+1) +".gif"); images[i] = getImage(getDocumentBase(),imageFile): //Register this image with the tracker tracker.addImage(images[i],i); } try { //Use tracker to make sure all the images are loaded tracker.waitForAll(); } catch (InterruptedException e) {} loaded = true; }

//Paint the current frame. public void paint (Graphics g) { if (loaded) { g.drawImage(offScrImage,0,0,this); } }

//Start ,setup our first image public void start() { if (tracker.checkID (index)) { offScrGC.drawImage (images[index],0,0,this); } animator = new Thread(this); animator.start(); }

//Run,do the animation work here. //Grab an image, pause ,grab the next... public void run() { //Get the id of the current thread Thread me = Thread.currentThread();

//If our animator thread exist,and is the current thread... while ((animatr!= null) && (animator==me)) { if ( tracker.checkID (index)) { //Clear the background and get the next image offScrGC.fillRect(0,0,100,100); offScrGCdrawImage(images[index],0,0,this); index++; //Loop back to the beginning and keep going if (index>= images.length) { index = 0; } } //Delay here so animation looks normal try { animator.sleep(200); }catch (InterruptedException e) {} //Draw the next frame repaint(); } } }

7.3 多 線 程 ?reg; 間 的 通 訊

7.3.1 生 產 者 和 消 費 者

多 線 程 的 一 個 重 要 特 點 是 它 們 ?reg; 間 可 以 互 相 通 訊。你 可 以 設 計 線 程 使 用 公 用 對 象, 每 個 線 程 都 可 以 獨 立 操作 公 用 對 象。 典 型 的 線 程 間 通 訊 建 立 在 生 產 者 和 消 費 者模 型 上: 一 個 線 程 產 生 輸 出; 另 一 個 線 程 使 用 輸 入。

buffer

讓 我 們 創 建 一 個 簡 單 的"Alphabet Soup"生 產 者 和 相應 的 消 費 者.

7.3.2 生 產 者

生 產 者 將 從thread類 裏 派 生: class Producer extends Thread { private Soup soup; private String alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";

public Producer(Soup s) { //Keep our own copy of the shared object soup = s; }

public void run() { char c; //Throw 10 letters into the soup for (int i=0;i<10;i++) { c = alphabet.charAt((int)(Math.random() *26)); soup.add(c); //print a record of osr addition System.out.println("Added"+c + "to the soup."); //wait a bit before we add the next letter try { sleep((int)(Math.random() *1000)); } catch (InterruptedException e) {} } } }

注 意 我 們 創 建 了Soup類 的 一 個 實 例。 生 產 者 用soup.add()函數 來 建 立 字 符 池。

7.3.3 消 費 者

讓 我 們 看 看 消 費 者 的 程 序: class Consumer extends Thread { private Soup soup;

public Consumer (Soup s) { //keep our own copy of the shared object soup = s; }

public void run() { char c; //Eat 10 letters from the alphabet soup for (int I=0 ;i<10;i++) { //grab one letter c = soup.eat(); //Print out the letter that we retrieved System.out.println("Ate a letter: " +c); //try { sleep((int)(Math.raddom()*2000)); } catch (InterruptedException e) {} } } }

同 理, 象 生 產 者 一 樣, 我 們 用soup.eat()來 處 理 信 息。 那 麼,Soup類到 底 幹 什 麼 呢?

7.3.4 監 視

Soup類 執 行 監 視 兩 個 線 程 ?reg; 間 傳 輸 信 息 的 功 能。 監 視是 多 線 程 中 不 可 缺 少 的 一 部 分, 因 爲 它 保 持 了 通 訊 的 流 ?copy;。 讓 我 們 看 看Soup.java文 件: class Soup { private char buffer[] = new char[6]; private int next = 0; //Flags to keep track of our buffer status private boolean isFull = false; private boolean isEmpty = true;

public syschronized char eat() { //We can't eat if there isn't anything in the buffer while (isEmpty == true) { try { wait() ;//we'll exit this when isEmpty turns false }catch (InterruptedException e) {} } //decrement the count,since we're going to eat one letter next--; //Did we eat the last letter? if (next== 0) { isEmpty = true; } //We know the buffer can't be full,because we just ate isFull = false; notify(); //return the letter to the thread that is eating return (buffer[next]); }

//method to add letters to the buffer public synchronized void add(char c) { //Wait around until there's room to add another letter while (isFull == true ) { try{ wait();//This will exit when isFull turns false }catch (InterruptedException e) {} } //add the letter to the next available spot buffer[next]=c; //Change the next available spot next++; //Are we full; if (next ==6) { isFull =true; } isEmpty =false; notify(); } }

soup類 包 含 兩 個 重 要 特 徵: 數 據 成 員buffer[]是 私 有 的, 功能 成 員add()和eat()是 公 有 的。

數 據 私 有 避 免 了 生 產 者 和 消 費 者 直 接 獲 得 數 據。 直 接訪 問 數 據 可 能 造 成 錯 誤。 例 如, 如 果 消 費 者 企 圖 從 空 緩 衝區 裏 取 出 數 據, 你 將 得 到 不 必 要 的 異 常, 否 則, 你 只 能 鎖住 進 程。 同 步 訪 問 方 法 避 免 了 破 壞 一 個 共 享 對 象。 當 生 產者 向soup裏 加 入 一 個 字 母 時, 消 費 者 不 能 吃 字 符, 諸 如 此 類。這 種 同 步 是 維 持 共 享 對 象 完 整 性 的 重 要 方 面。notify()函 數將 喚 醒 每 一 個 等 待 線 程。 等 待 線 程 將 繼 續 它 的 訪 問。

7.3.5 聯 系 起 來

現 在 我 們 有 一 個 生 產 者, 一 個 消 費 者 和 一 個 共 享 對 象,怎 樣 實 現 它 們 的 交 互 呢? 我 們 只 需 要 一 個 簡 單 的 控 制 程序 來 啓 動 所 有 的 線 程 並 確 信 每 一 個 線 程 都 是 訪 問 的 同 一個 共 享 對 象。 下 面 是 控 制 程 序 的 代 碼,SoupTest.java: class SoupTest { public static void main(String args[]) { Soup s = new Soup(); Producer p1 = new Producer(s); Consumer c1 = new Consumer(s);

p1.start(); c1.start(); } }

7.3.6 監 視 生 產 者

生 產 者/消 費 者 模 型 程 序 經 常 用 來 實 現 遠 程 監 視 功 能,它 讓 消 費 者 看 到 生 產 者 同 用 戶 的 交 互 或 同 系 統 其 它 部 分的 交 互。 例 如, 在 網 絡 中, 一 組 生 產 者 線 程 可 以 在 很 多 工作 站 上 運 行。 生 產 者 可 以 打 印 文 檔, 文 檔 打 印 後, 一 個 標誌 將 保 存 下 來。 一 個(或 多 個?copy; 消 費 者 將 保 存 標 志 並 在晚 上 報 告 白 天 打 印 活 動 的 情 況。 另 外, 還 有 例 子 在 一 個 工作 站 是 分 出 幾 個 獨 立 的 窗 口。 一 個 窗 口 用 作 用 戶 輸 入(生產 者?copy;, 另 一 個 窗 口 作 出 對 輸 入 的 反 應(消 費 者?copy;。

7.4 線 程API列 表

下 面 是 一 ?copy; 常 用 的 線 程 類 的 方 法 函 數 列 表:

類 函 數: 以 下 是Thread的 靜 態 函 數, 即 可 以 直 接 從Thread類調 用。

currentThread 返 回 正 在 運 行 的Thread對 象 yield 停 止 運 行 當 前線 程, 讓 系 統 運 行 下 一 個 線 程 sleep(int n) 讓 當 前 線 程 睡 眠n毫秒

對 象 函 數: 以 下 函 數 必 須 用Thread的 實 例 對 象 來 調 用。

start start函 數 告 訴java運 行 系 統 爲 本 線 程 建 立 一 個 執 行環 境, 然 後 調 用 本 線 程 的run()函 數。 run 是 運 行 本 線 程 的 將要 執 行 的 代 碼, 也 是Runnable接 口 的 唯 一 函 數。 當 一 個 線 程初 始 化 後, 由start函 數 來 調 用 它, 一 ?copy;run函 數 返 回, 本線 程 也 就 終 止 了。 stop 讓 某 線 程 馬 上 終 止, 系 統 將 刪 除 本線 程 的 執 行 環 境 suspend 與stop函 數 不 同,suspend將 線 程 暫 停 執行, 但 系 統 不 破 壞 線 程 的 執 行 環 境, 你 可 以 用resume來 恢 複本 線 程 的 執 行 resume 恢 復 被 掛 起 的 線 程 進 入 運 行 狀 態 setPriority(int p) 給 線 程 設 置 優 先 級 getPriority 返 回 線 程 的 優 先 級 setName(String name) 給 線 程 設 置 名 稱 getName 取 線 程 的 名 稱

本 章 小 結:

1.多 線 程 是java語 言 的 重 要 特 點,java語 言 用Thread類 封 裝 了線 程 的 所 有 操 作。 2.線 程 的 接 口 名 爲Runnable 3.線 程 ?reg; 間同 步 機 制 爲synchronized關 鍵 詞 4.線 程 ?reg; 間 通 訊 靠wait與notify消息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章