程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java 線 程 的 討 論 與 應 用

Java 線 程 的 討 論 與 應 用

編輯:關於JAVA

一、 為 什 麼 要 研 究 和 使 用 線 程

一 般 來 說, 計 算 機 正 在 執 行 的 程 序 稱 作 進 程(process), 進 程 有 不 同 的 地 址 空 間 並 且 是 在 同 一 系 統 上 運 行 的 不 同 程 序, 如 W O R D 和Excel, 進 程 間 的 通 訊 是 很 費 時 而 且 有 限 的。 上 下 文 切 換、 改 變 運 行 的 進 程 也 是 非 常 復 雜 的。 進 程 間 通 訊 復 雜, 可 能 需 要 管 道、 消 息 隊 列、 共 享 內 存(sharedmemory) 或 信 號 處 理 來 保 證 進 程 間 的 通 訊。 盡 管 許 多 程 序 都 在 運 行, 但 一 次 只 能 與 一 個 程 序 打 交 道。

線 程(thread) 是 指 進 程 中 單 一 順 序 的 控 制 流。 又 稱 為 輕 量 級 進 程。 線 程 則 共 享 相 同 的 地 址 空 間 並 共 同 構 成 一 個 大 的 進 程。 線 程 間 的 通 訊 是 非 常 簡 單 而 有 效 的, 上 下 文 切 換 非 常 快 並 且 是 整 個 大 程 序 的 一 部 分 切 換。 線 程 僅 是 過 程 調 用, 它 們 彼 此 獨 立 執 行, 線 程 使 得 在 一 個 應 用 程 序 中, 程 序 的 編 寫 更 加 自 由 和 豐 富。 線 程 的 興 趣 在 於, 一 個 程 序 中 同 時 使 用 多 個 線 程 來 完 成 不 同 的 任 務。 因 此 如 果 很 好 地 利 用 線 程, 可 以 大 大 簡 化 應 用 程 序 設 計。 多 線 程 可 以 增 進 程 序 的 交 互 性, 提 供 更 好 的 能 力 和 功 能、 更 好 的GUI 和 更 好 的 服 務 器 功 能。 給 二 個 例 子 說 明 如 下:

例 一: 利 用 多 線 程 並 行 機 制 可 以 很 好 地 解 決 交 互 式 網 絡 程 序 中 的 許 多 問 題, 如: 大 量 的 網 絡 文 件 資 源 的 讀 寫、 用 戶 輸 入 響 應、 動 畫 顯 示 等 問 題 不 需 要 C P U 的 多 少 時 間; 而 耗 時 的 復 雜 計 算 通 常 並 不 需 要 立 即 響 應, 所 以 無 需 將 C P U 全 給 它。 例 如, 從 一 個 慢 速 的 網 絡 上 讀 取 一 數 據 流 也 許 要 1 分 鐘 時 間, 但 需 要 C P U 參 與 傳 輸 數 據 的 時 間 則 非 常 短; 響 應 用 戶 的 輸 入 如 擊 鍵, 就 算 最 快 的 輸 入 員, 1 秒 鐘 擊 鍵 1 0 次, 也 不 需 要 C P U 的 多 少 時 間。 動 畫 程 序 比 較 耗 時, 一 幅 畫 在 1 秒 內 要 重 繪 5 - 1 0 次, 但 C P U 在 大 部 分 時 間 仍 處 於 空 閒 狀 態。 在 傳 統 的 單 線 程 環 境 下 的 問 題 是 用 戶 必 須 等 待 每 個 任 務 完 成 後 才 能 進 行 下 一 個 任 務。 即 使 C P U 大 部 分 時 間 空 閒, 也 只 能 按 步 就 班 地 工 作。 多 線 程 可 以 很 好 地 解 決 這 些 問 題 避 免 引 起 用 戶 的 等 待。 如: 耗 時 的 復 雜 計 算 應 用 就 可 劃 分 成 兩 個 控 制 線 程: 一 個 處 理GUI 的 用 戶 事 件, 另 一 個 進 行 後 台 計 算。

例 二: 如 並 發 服 務 器, 它 面 向 不 定 長 時 間 內 處 理 完 的 請 求, 對 每 個 請 求 由 服 務 器 的 線 程 處 理。 傳 統 的 並 發 服 務 器 往 往 是 基 於 多 進 程 機 制 的, 每 個 客 戶 一 個 進 程, 需 要 操 作 系 統 的 干 預, 進 程 的 數 目 受 操 作 系 統 的 限 制。 本 文 利 用Java 的 線 程 機 制 建 立 了 基 於 多 線 程 的 並 發 服 務 器。 生 成 和 管 理 他 們 是 相 當 簡 單 的 操 作。 線 程 被 用 來 建 立 請 求 驅 動 的 服 務 程 序, 每 個 客 戶 一 個 線 程, 多 個 線 程 可 以 並 發 執 行。 特 別 地 線 程 具 有 如 下 特 性(1) 線 程 共 享 父 進 程 的 所 有 程 序 和 數 據(2) 有 自 身 的 運 行 單 元(3) 有 它 自 己 的 私 有 存 儲 和 執 行 環 境( 尤 其 是 處 理 器 寄 存 器), 使 得 服 務 器 進 程 不 隨 客 戶 數 的 增 加 而 線 性 增 加。 可 減 少 服 務 器 進 程 的 壓 力, 降 低 開 銷, 充 分 利 用CPU 的 資 源。 以 上 並 發 服 務 器 在 某 一 瞬 間 由 同 一 服 務 器 進 程 所 產 生 的 多 個 並 發 線 程 對 多 個 客 戶 的 並 發 請 求 采 取 分 而 治 之 的 措 施, 從 而 解 決 了 並 發 請 求 的 問 題。 各 線 程 即 可 以 獨 立 操 作, 又 可 以 協 同 作 業。 降 低 了 服 務 器 的 復 雜 度。

Java 是 基 於 操 作 系 統 級 的 多 線 程 環 境 之 上 設 計 的,Java 的 運 行 器 依 靠 多 線 程 來 執 行 任 務, 並 且 所 有 類 庫 在 設 計 時 都 考 慮 到 多 線 程 機 制。

二、Java 線 程 的 結 構

Java 支 持 一 種“ 搶 占 式”(preemptive) 調 度 方 式。

線 程 從 產 生 到 消 失, 可 分5 個 狀 態:

Newborn

線 程 在 己 被 創 建 但 未 執 行 這 段 時 間 內, 處 於 一 個 特 殊 的"Newborn" 狀 態, 這 時, 線 程 對 象 己 被 分 配 內 存 空 間, 其 私 有 數 據 己 被 初 始 化, 但 該 線 程 還 未 被 調 度。 此 時 線 程 對 象 可 通 過start() 方 法 調 度, 或 者 利 用stop() 方 法 殺 死. 新 創 建 的 線 程 一 旦 被 調 度, 就 將 切 換 到"Runnable" 狀 態。

Runnable

Runnable 意 即 線 程 的 就 緒 狀 態, 表 示 線 程 正 等 待 處 理 器 資 源, 隨 時 可 被 調 用 執 行。 處 於 就 緒 狀 態 的 線 程 事 實 上 己 被 調 度, 也 就 是 說, 它 們 己 經 被 放 到 某 一 隊 列 等 待 執 行。 處 於 就 緒 狀 態 的 線 程 何 時 可 真 正 執 行, 取 決 於 線 程 優 先 級 以 及 隊 列 的 當 前 狀 況。 線 程 的 優 先 級 如 果 相 同, 將 遵 循" 先 來 先 服 務" 的 調 度 原 則。

線 程 依 據 自 身 優 先 級 進 入 等 待 隊 列 的 相 應 位 置。 某 些 系 統 線 程 具 有 最 高 優 先 級, 這 些 最 高 優 先 級 線 程 一 旦 進 入 就 緒 狀 態, 將 搶 占 當 前 正 在 執 行 的 線 程 的 處 理 器 資 源, 當 前 線 程 只 能 重 新 在 等 待 隊 列 尋 找 自 己 的 位 置. 這 些 具 有 最 高 優 先 級 的 線 程 執 行 完 自 己 的 任 務 之 後, 將 睡 眠 一 段 時 間, 等 待 被 某 一 事 件 喚 醒. 一 旦 被 喚, 這 些 線 程 就 又 開 始 搶 占 處 理 器 資 源。 這 些 最 高 優 先 級 線 程 通 常 用 來 執 行 一 些 關 鍵 性 任 務, 如 屏 幕 顯 示。

低 優 先 級 線 程 需 等 待 更 長 的 時 間 才 能 有 機 會 運 行。 由 於 系 統 本 身 無 法 中 止 高 優 先 級 線 程 的 執 行, 因 此, 如 果 你 的 程 序 中 用 到 了 優 先 級 較 高 的 線 程 對 象, 那 麼 最 好 不 時 讓 這 些 線 程 放 棄 對 處 理 器 資 源 的 控 制 權, 以 使 其 他 線 程 能 夠 有 機 運 行。

Running

"Running"( 運 行) 狀 態 表 明 線 程 正 在 運 行, 該 線 己 經 擁 有 了 對 處 理 器 的 控 制 權, 其 代 碼 目 前 正 在 運 行。 這 個 線 程 將 一 直 運 行 直 到 運 行 完 畢, 除 非 運 行 過 程 的 控 制 權 被 一 優 先 級 更 高 的 線 程 強 占。

綜 合 起 來, 線 程 在 如 下3 種 情 形 之 下 將 釋 放 對 處 理 器 的 控 制 權:

1. 主 動 或 被 動 地 釋 放 對 處 理 器 資 源 的 控 制 權。 這 時, 該 線 程 必 須 再 次 進 入 等 待 隊 列, 等 待 其 他 優 先 級 高 或 相 等 線 程 執 行 完 畢。

2. 睡 眠 一 段 確 定 的 時 間, 不 進 入 等 待 隊 列。 這 段 確 定 的 時 間 段 到 期 之 後, 重 新 開 始 運 行。

3. 等 待 某 一 事 件 喚 醒 自 己。

Blocked

一 個 線 程 如 果 處 於"Blocked"( 堵 塞) 狀 態, 那 麼 暫 時 這 個 線 程 將 無 法 進 入 就 緒 隊 列。 處 於 堵 塞 狀 態 的 線 程 通 常 必 須 由 某 些 事 件 才 能 喚 醒。 至 於 是 何 種 事 件, 則 取 決 於 堵 塞 發 生 的 原 因: 處 於 睡 眠 中 的 線 程 必 須 被 堵 塞 一 段 固 定 的 時 間; 被 掛 起、 或 處 於 消 息 等 待 狀 態 的 線 程 則 必 須 由 一 外 來 事 件 喚 醒。

Dead

Dead 表 示 線 程 巳 退 出 運 行 狀 態, 並 且 不 再 進 入 就 緒 隊 列. 其 中 原 因 可 能 是 線 程 巳 執 行 完 畢( 正 常 結 束), 也 可 能 是 該 線 程 被 另 一 線 程 所 強 行 中 斷(kill)。

三、 創 建 和 使 用 線 程 的 基 本 方 法

1. 線 程 的 產 生

在Java 語 言 中, 可 采 用 兩 種 方 式 產 生 線 程: 一 是 實 現 一 個Runnable 界 面, 二 是 擴 充 一 個Thread 類.Java.lang 中 定 義 了 一 個 直 接 從 根 類Object 中 派 生 的Thread 類. 所 有 以 這 個 類 派 生 的 子 類 或 間 接 子 類, 均 為 線 程。 在 這 種 方 式 中, 需 要 作 為 一 個 線 程 執 行 的 類 只 能 繼 承、 擴 充 單 一 的 父 類。 下 面 的 例 子 通 過 擴 充Thread 類, 用 該 線 程 自 己 的 實 現 來 覆 蓋Thread.run(), 產 生 一 個 新 類Counter。run () 方 法 是Counter 類 線 程 所 作 的 全 部 操 作.

import Java.lang.*;

public class Counter extends Thread

{

public void run ()

{....}

}

實 現Runnable 界 面 是 最 常 用 的 產 生 線 程 的 方 法, 它 打 破 了 擴 充Thread 類 方 式 的 限 制。

Java 語 言 源 碼 中,Runnable 界 面 只 包 含 了 一 個 抽 象 方 法, 其 定 義 如 下:

package Java.lang.*;

public interface Runnable {

public abstract void run ();

}

所 有 實 現 了Runnable 界 面 的 類 的 對 象 都 可 以 以 線 程 方 式 執 行. 下 面 的 例 子 產 生 與 上 面 例 子 相 同 的 類. 可 以 看 到counter 類 中 使 用 了 一 個Thread 類 的 變 量.

import Java.lang.*;

public class counter implements Runnable

{ Thread T;

public void run ()

{...}

}

2、 基 本 方 法

.public synchronized void start()

啟 動 線 程 對 象, 調 用 其run() 方 法, 隨 即 返 回。

.pubilc final void stop()

停 止 線 程 的 執 行。

.public final void resume()

喚 醒 被 掛 起 的 線 程。 只 在 調 用suspend() 之 後 有 效。

.public final void suspend()

掛 起 線 程 的 執 行。

.public static void yIEld()

暫 時 中 止 當 前 正 在 執 行 的 線 程 對 象 的 運 行。 若 存 在 其 他 線 程, 則 隨 後 調 用 下 一 個 線 程。

.public static void sleep (long mills)throws InterruptedException

使 當 前 正 處 運 行 狀 態 的 線 程 睡 眠mills 毫 秒。

.public final void wait() throws InterruptedException

使 線 程 進 入 等 待 狀 態, 直 到 被 另 一 線 程 喚 醒

.public final void motify()

把 線 程 狀 態 的 變 化 通 知 給 另 一 等 待 線 程。

四、 線 程 的 同 步

線 程 的 使 用, 主 要 在 於 一 個 進 程 中 多 個 線 程 的 協 同 工 作, 所 以 線 程 的 同 步 就 很 重 要。 線 程 的 同 步 用 於 線 程 共 享 數 據, 轉 換 和 控 制 線 程 的 執 行, 保 證 內 存 的 一 致 性。

在 Java 中, 運 行 環 境 使 用 程 序( Monitor) 來 解 決 線 程 同 步 的 問 題。 管 程 是 一 種 並 發 同 步 機 制, 它 包 括 用 於 分 配 一 個 特 定 的 共 享 資 源 或 一 組 共 享 資 源 的 數 據 和 方 法.

Java 為 每 一 個 擁 有 synchronized 方 法 的 對 象 實 例 提 供 了 一 個 唯 一 的 管 程。 為 了 完 成 分 配 資 源 的 功 能, 線 程 必 須 調 用 管 程 入 口。 管 程 入 口 就 是synchronized 方 法 入 口。 當 調 用 同 步( synchronized) 方 法 時, 該 線 程 就 獲 得 了 該 管 程。

管 程 邊 界 上 實 行 嚴 格 的 互 斥, 在 同 一 時 刻, 只 允 許 一 個 線 程 進 入 管 程; 當 管 程 中 已 有 了 一 個 線 程 時, 其 它 希 望 進 入 管 程 的 線 程 必 須 等 待, 這 種 等 待 是 由 管 程 自 動 管 理 的。

如 果 調 用 管 程 入 口 的 線 程 發 現 資 源 已 被 分 配, 管 程 中 的 這 個 線 程 將 調 用 等 待 操 作wait()。 進 入wait() 後, 該 線 程 放 棄 占 用 管 程, 在 管 程 外 面 等 待, 以 便 其 它 線 程 進 入 管 程。

最 終, 占 用 資 源 的 線 程 將 調 用 一 個 管 程 的 入 口 把 資 源 歸 還 給 系 統, 此 時, 該 線 程 需 調 用 一 個 通 知 操 作notify(), 通 知 系 統 允 許 其 中 一 個 等 待 的 線 程 獲 得 管 程 並 得 到 資 源。 被 通 知 的 線 程 是 排 隊 的, 從 而 避 免 無 限 拖 延。

在 Java.lang 中 提 供 了 用 來 編 寫 管 程 的 兩 個 方 法: notify() 和wait()。 此 外 還 有notifyAll(), 它 通 知 所 有 等 待 的 線 程, 使 它 們 競 爭 管 程, 結 果 是 其 中 一 個 獲 得 管 程, 其 佘 返 回 等 待 狀 態。

五、 線 程 的 控 制

線 程 的 控 制 分 為 停 止 線 程 和 啟 動 線 程。

.public final void suspend()

掛 起 線 程 的 執 行。

.public final void resume()

喚 醒 被 掛 起 的 線 程。 使 一 個 暫 停 的 線 程 可 用 於 調 度。

因 為 線 程 的 調 度 為 搶 占 式 機 制, 也 可 使 用 線 程 的 優 先 級 來 對 線 程 進 行 控 制。

.public final void setPriority(int newPriority)

設 置 線 程 優 先 級。

.public final int getPriority()

獲 取 並 返 回 線 程 的 優 先 級。

線 程 的 優 先 級 用 於 在 運 行 隊 列 中 給 線 程 排 序,Java 提 供 的 搶 占 式 調 度, 使 得 高 級 別 的 線 程 先 運 行。

六、 線 程 的 應 用

在 實 際 應 用 中, 線 程 使 用 的 范 圍 很 廣, 可 用 於 控 制 實 時 數 據 處 理、 快 速 的 網 絡 服 務, 還 有 更 快 的 圖 象 繪 制 和 打 印, 以 及 數 據 庫 中 的 數 據 的 取 回 和 處 理 等 等。 在Java 中 一 個 在 不 停 運 行 的 提 供 一 些 基 本 服 務 的 例 子 是 垃 圾 收 集 線 程, 垃 圾 收 集 線 程,。 該 線 程 由Java 虛 擬 機 提 供。 它 掃 描 程 序 中 不 再 被 訪 問 的 變 量, 將 其 所 占 的 系 統 資 源 釋 放 給 系 統。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved