溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

實(shí)現(xiàn)Runnable接口的多線程程序設(shè)計(jì)方法是什么

發(fā)布時(shí)間:2022-01-11 09:38:36 來源:億速云 閱讀:114 作者:柒染 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)實(shí)現(xiàn)Runnable接口的多線程程序設(shè)計(jì)方法是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

實(shí)現(xiàn)Runnable接口的多線程程序設(shè)計(jì)方法
  Java語言中提供的另外一種實(shí)現(xiàn)多線程應(yīng)用程序的方法是多線程對象實(shí)現(xiàn)Runnable接口并且在該類中定義用于啟動線程的run方法。這種定義方式的好處在于多線程應(yīng)用對象可以繼承其它對象而不是必須繼承Thread類,從而能夠增加類定義的邏輯性。
  實(shí)現(xiàn)Runnable接口的多線程應(yīng)用程序框架代碼如下所示:
  
  //Consumer.java
  import java.util.*;
  class Consumer implements Runnable
  {
   … …
  public Consumer(int nTime, String strConsumer){… …}
  public void run(){… …}
  static public void main(String args[])
  {
  Thread aConsumer = new Thread(new Consumer(1000, "aConsumer"));
  aConsumer.start();
  //其它對象實(shí)例的運(yùn)行線程
   //… …
   }
  }
  
  從上述代碼可以看出:該類實(shí)現(xiàn)了Runnable接口并且在該類中定義了run方法。這種多線程應(yīng)用程序的實(shí)現(xiàn)方式與繼承Thread類的多線程應(yīng)用程序的重要區(qū)別在于啟動多線程對象的方法設(shè)計(jì)方法不同。在上述代碼中,通過創(chuàng)建Thread對象實(shí)例并且將應(yīng)用對象作為創(chuàng)建Thread類實(shí)例的參數(shù)。

  線程間的同步
  
  Java應(yīng)用程序的多個(gè)線程共享同一進(jìn)程的數(shù)據(jù)資源,多個(gè)用戶線程在并發(fā)運(yùn)行過程中可能同時(shí)訪問具有敏感性的內(nèi)容。在Java中定義了線程同步的概念,實(shí)現(xiàn)對共享資源的一致性維護(hù)。下面以筆者最近開發(fā)的移動通信計(jì)費(fèi)系統(tǒng)中線程間同步控制方法,說明Java語言中多線程同步方式的實(shí)現(xiàn)過程。
  
  在沒有多線程同步控制策略條件下的客戶賬戶類定義框架代碼如下所示:
  
  public class RegisterAccount
  {
  float fBalance;
  //客戶繳費(fèi)方法
  public void deposit(float fFees){ fBalance += fFees; }
  //通話計(jì)費(fèi)方法
  public void withdraw(float fFees){ fBalance -= fFees; }
  … …
  }
  
  
  
  
  讀者也許會認(rèn)為:上述程序代碼完全能夠滿足計(jì)費(fèi)系統(tǒng)實(shí)際的需要。確實(shí),在單線程環(huán)境下該程序確實(shí)是可靠的。但是,多進(jìn)程并發(fā)運(yùn)行的情況是怎樣的呢?假設(shè)發(fā)生這種情況:客戶在客戶服務(wù)中心進(jìn)行繳費(fèi)的同時(shí)正在利用移動通信設(shè)備僅此通話,客戶通話結(jié)束時(shí)計(jì)費(fèi)系統(tǒng)啟動計(jì)費(fèi)進(jìn)程,而同時(shí)服務(wù)中心的工作人員也提交繳費(fèi)進(jìn)程運(yùn)行。讀者可以看到如果發(fā)生這種情況,對客戶賬戶的處理是不嚴(yán)肅的。
  
  如何解決這種問題呢?很簡單,在RegisterAccount類方法定義中加上用于標(biāo)識同步方法的關(guān)鍵字synchronized。這樣,在同步方法執(zhí)行過程中該方法涉及的共享資源(在上述代碼中為fBalance成員變量)將被加上共享鎖,以確保在方法運(yùn)行期間只有該方法能夠?qū)蚕碣Y源進(jìn)行訪問,直到該方法的線程運(yùn)行結(jié)束打開共享鎖,其它線程才能夠訪問這些共享資源。在共享鎖沒有打開的時(shí)候其它訪問共享資源的線程處于阻塞狀態(tài)。
  
  進(jìn)行線程同步策略控制后的RegisterAccount類定義如下面代碼所示:
  
  public class RegisterAccount
  {
  float fBalance;
  public synchronized void deposit(float fFees){ fBalance += fFees; }
  public synchronized void withdraw(float fFees){ fBalance -= fFees; }
  … …
  }
  
  從經(jīng)過線程同步機(jī)制定義后的代碼形式可以看出:在對共享資源進(jìn)行訪問的方法訪問屬性關(guān)鍵字(public)后附加同步定義關(guān)鍵字 synchronized,使得同步方法在對共享資源訪問的時(shí)候,為這些敏感資源附加共享鎖來控制方法執(zhí)行期間的資源獨(dú)占性,實(shí)現(xiàn)了應(yīng)用系統(tǒng)數(shù)據(jù)資源的一致性管理和維護(hù)。



免費(fèi)注冊
用戶登陸
幫助中心





Matrix首頁 Matrix動態(tài) 技術(shù)專欄 資源下載 精彩推薦 網(wǎng)站留言 用戶中心 Matrix論壇




今天是:2003年7月16日 星期三 您現(xiàn)在位于: 首頁 → 技術(shù)專欄 → java核心技術(shù)(java基礎(chǔ)技術(shù))


JAVA教程:解析Java的多線程機(jī)制(5)
2003-6-7 Matrix讓你不斷進(jìn)步 瀏覽選項(xiàng): 顏色 默認(rèn) 灰度 橄欖色 綠色 藍(lán)色 褐色 紅色 本文已被瀏覽 31 次



Java線程的管理
  
  
  線程的狀態(tài)控制
  
  在這里需要明確的是:無論采用繼承Thread類還是實(shí)現(xiàn)Runnable接口來實(shí)現(xiàn)應(yīng)用程序的多線程能力,都需要在該類中定義用于完成實(shí)際功能的run方法,這個(gè)run方法稱為線程體(Thread Body)。按照線程體在計(jì)算機(jī)系統(tǒng)內(nèi)存中的狀態(tài)不同,可以將線程分為創(chuàng)建、就緒、運(yùn)行、睡眠、掛起和死亡等類型。這些線程狀態(tài)類型下線程的特征為:
  
  創(chuàng)建狀態(tài):當(dāng)利用new關(guān)鍵字創(chuàng)建線程對象實(shí)例后,它僅僅作為一個(gè)對象實(shí)例存在,JVM沒有為其分配CPU時(shí)間片等線程運(yùn)行資源;
  
  就緒狀態(tài):在處于創(chuàng)建狀態(tài)的線程中調(diào)用start方法將線程的狀態(tài)轉(zhuǎn)換為就緒狀態(tài)。這時(shí),線程已經(jīng)得到除CPU時(shí)間之外的其它系統(tǒng)資源,只等JVM的線程調(diào)度器按照線程的優(yōu)先級對該線程進(jìn)行調(diào)度,從而使該線程擁有能夠獲得CPU時(shí)間片的機(jī)會。
  
  睡眠狀態(tài):在線程運(yùn)行過程中可以調(diào)用sleep方法并在方法參數(shù)中指定線程的睡眠時(shí)間將線程狀態(tài)轉(zhuǎn)換為睡眠狀態(tài)。這時(shí),該線程在不釋放占用資源的情況下停止運(yùn)行指定的睡眠時(shí)間。時(shí)間到達(dá)后,線程重新由JVM線程調(diào)度器進(jìn)行調(diào)度和管理。
  
  掛起狀態(tài):可以通過調(diào)用suspend方法將線程的狀態(tài)轉(zhuǎn)換為掛起狀態(tài)。這時(shí),線程將釋放占用的所有資源,由JVM調(diào)度轉(zhuǎn)入臨時(shí)存儲空間,直至應(yīng)用程序調(diào)用resume方法恢復(fù)線程運(yùn)行。
  
  死亡狀態(tài):當(dāng)線程體運(yùn)行結(jié)束或者調(diào)用線程對象的stop方法后線程將終止運(yùn)行,由JVM收回線程占用的資源。
  
  在Java線程類中分別定義了相應(yīng)的方法,用于在應(yīng)用程序中對線程狀態(tài)進(jìn)行控制和管理。
  
  線程的調(diào)度
  
  線程調(diào)用的意義在于JVM應(yīng)對運(yùn)行的多個(gè)線程進(jìn)行系統(tǒng)級的協(xié)調(diào),以避免多個(gè)線程爭用有限資源而導(dǎo)致應(yīng)用系統(tǒng)死機(jī)或者崩潰。
  
  為了線程對于操作系統(tǒng)和用戶的重要性區(qū)分開,Java定義了線程的優(yōu)先級策略。Java將線程的優(yōu)先級分為10個(gè)等級,分別用1-10之間的數(shù)字表示。數(shù)字越大表明線程的級別越高。相應(yīng)地,在Thread類中定義了表示線程最低、最高和普通優(yōu)先級的成員變量MIN_PRIORITY、 MAX_PRIORITY和NORMAL_PRIORITY,代表的優(yōu)先級等級分別為1、10和5。當(dāng)一個(gè)線程對象被創(chuàng)建時(shí),其默認(rèn)的線程優(yōu)先級是5。
  
  為了控制線程的運(yùn)行策略,Java定義了線程調(diào)度器來監(jiān)控系統(tǒng)中處于就緒狀態(tài)的所有線程。線程調(diào)度器按照線程的優(yōu)先級決定那個(gè)線程投入處理器運(yùn)行。在多個(gè)線程處于就緒狀態(tài)的條件下,具有高優(yōu)先級的線程會在低優(yōu)先級線程之前得到執(zhí)行。線程調(diào)度器同樣采用"搶占式"策略來調(diào)度線程執(zhí)行,即當(dāng)前線程執(zhí)行過程中有較高優(yōu)先級的線程進(jìn)入就緒狀態(tài),則高優(yōu)先級的線程立即被調(diào)度執(zhí)行。具有相同優(yōu)先級的所有線程采用輪轉(zhuǎn)的方式來共同分配CPU時(shí)間片。
  
  在應(yīng)用程序中設(shè)置線程優(yōu)先級的方法很簡單,在創(chuàng)建線程對象之后可以調(diào)用線程對象的setPriority方法改變該線程的運(yùn)行優(yōu)先級,同樣可以調(diào)用getPriority方法獲取當(dāng)前線程的優(yōu)先級。
  
  在Java中比較特殊的線程是被稱為守護(hù)(Daemon)線程的低級別線程。這個(gè)線程具有最低的優(yōu)先級,用于為系統(tǒng)中的其它對象和線程提供服務(wù)。將一個(gè)用戶線程設(shè)置為守護(hù)線程的方式是在線程對象創(chuàng)建之前調(diào)用線程對象的setDaemon方法。典型的守護(hù)線程例子是JVM中的系統(tǒng)資源自動回收線程,它始終在低級別的狀態(tài)中運(yùn)行,用于實(shí)時(shí)監(jiān)控和管理系統(tǒng)中的可回收資源。
  
  線程分組管理
  
  Java定義了在多線程運(yùn)行系統(tǒng)中的線程組(ThreadGroup)對象,用于實(shí)現(xiàn)按照特定功能對線程進(jìn)行集中式分組管理。用戶創(chuàng)建的每個(gè)線程均屬于某線程組,這個(gè)線程組可以在線程創(chuàng)建時(shí)指定,也可以不指定線程組以使該線程處于默認(rèn)的線程組之中。但是,一旦線程加入某線程組,該線程就一直存在于該線程組中直至線程死亡,不能在中途改變線程所屬的線程組。
  
  當(dāng)Java的Application應(yīng)用程序運(yùn)行時(shí),JVM創(chuàng)建名稱為main的線程組。除非單獨(dú)指定,在該應(yīng)用程序中創(chuàng)建的線程均屬于 main線程組。在main線程組中可以創(chuàng)建其它名稱的線程組并將其它線程加入到該線程組中,依此類推,構(gòu)成線程和線程組之間的樹型管理和繼承關(guān)系。
  與線程類似,可以針對線程組對象進(jìn)行線程組的調(diào)度、狀態(tài)管理以及優(yōu)先級設(shè)置等。在對線程組進(jìn)行管理過程中,加入到某線程組中的所有線程均被看作統(tǒng)一的對象。

  
  與其它操作系統(tǒng)環(huán)境不同,Java運(yùn)行環(huán)境中的線程類似于多用戶、多任務(wù)操作系統(tǒng)環(huán)境下的進(jìn)程,但在進(jìn)程和線程的運(yùn)行及創(chuàng)建方式等方面,進(jìn)程與Java線程具有明顯區(qū)別。
  Unix操作系統(tǒng)環(huán)境下,應(yīng)用程序可以利用fork函數(shù)創(chuàng)建子進(jìn)程,但子進(jìn)程與該應(yīng)用程序進(jìn)程擁有獨(dú)立的地址空間、系統(tǒng)資源和代碼執(zhí)行單元,并且進(jìn)程的調(diào)度是由操作系統(tǒng)來完成的,使得在應(yīng)用進(jìn)程之間進(jìn)行通信和線程協(xié)調(diào)相對復(fù)雜。而Java應(yīng)用程序中的多線程則是共享同一應(yīng)用系統(tǒng)資源的多個(gè)并行代碼執(zhí)行體,線程之間的通信和協(xié)調(diào)方法相對簡單。
  可以說:Java語言對應(yīng)用程序多線程能力的支持增強(qiáng)了Java作為網(wǎng)絡(luò)程序設(shè)計(jì)語言的優(yōu)勢,為實(shí)現(xiàn)分布式應(yīng)用系統(tǒng)中多客戶端的并發(fā)訪問以及提高服務(wù)器的響應(yīng)效率奠定堅(jiān)實(shí)基礎(chǔ)。

關(guān)于實(shí)現(xiàn)Runnable接口的多線程程序設(shè)計(jì)方法是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI