1. gzyueqian
      13352868059

      Java基礎(chǔ) 獲取java線程中信息的兩種方法

      更新時(shí)間: 2008-04-10 14:16:14來(lái)源: 粵嵌教育瀏覽量:837

        【賽迪網(wǎng)技術(shù)社區(qū)整理】在進(jìn)行多線程編程中,比較重要也是比較困難的一個(gè)操作就是如何獲取線程中的信息。大多數(shù)人會(huì)采取比較常見的一種方法就是將線程中要返回的結(jié)果存儲(chǔ)在一個(gè)字段中,然后再提供一個(gè)獲取方法將這個(gè)字段的內(nèi)容返回給該方法的調(diào)用者。如以下的ReturnThreadInfo類:

      package threadtest1;

      /**

      *

      * @author shi mingxiang

      */

      public class ReturnThreadInfo extends Thread {

      private String str;


      public ReturnThreadInfo() {

      this.str = "Hello";

      }


      public void run(){

      this.str = "Hello World!";

      }


      public String getThreadInfo(){

      return this.str;

      }

      }

        大家可以看到該類是一個(gè)線程類并含有一個(gè)初始值為"Hello"的字段str以及一個(gè)可以返回str值的方法:getThreadInfo(),而且當(dāng)這個(gè)線程啟動(dòng)后str會(huì)被賦于新值:"Hello World!"。現(xiàn)在我想在另外一個(gè)類中啟動(dòng)ReturnThreadInfo線程,并通過(guò)getThreadInfo()方法獲取值為"Hello World!"的變量并打印輸出到控制臺(tái)中。以下給出一個(gè)實(shí)現(xiàn)該功能的Main類:

      package threadtest1;

      /**

      *

      * @author shi mingxiang

      */

      public class Main{


      public Main() {

      }


      /**

      * @param args the command line arguments

      */

      public static void main(String[] args) {

      ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();

      returnThreadInfo.start();//創(chuàng)建并啟動(dòng)ReturnThreadInfo線程

      System.out.println(returnThreadInfo.getThreadInfo());//獲取并輸出returnThreadInfo對(duì)象的str的值

      }


      }

        以上是一個(gè)多數(shù)熟悉單線程編程的人在反應(yīng)下給出的實(shí)現(xiàn)方法。但是該類在運(yùn)行的時(shí)候輸出的結(jié)果卻不是期望的"Hello World!"而是"Hello",這是由于線程的競(jìng)爭(zhēng)條件導(dǎo)致的(由于ReturnThreadInfo線程和Main線程的優(yōu)先級(jí)都為5,所以在很大幾率上ReturnThreadInfo線程的run()方法還沒(méi)有運(yùn)行,Main類就已經(jīng)運(yùn)行System.out.println(returnThreadInfo.getThreadInfo());將"Hello"輸出了。具體的原理可以參見另一篇文章:"java多線程的幾點(diǎn)誤區(qū)")。有的人可能會(huì)立即想到把ReturnThreadInfo線程的優(yōu)先級(jí)設(shè)高些(比如的10)就可以returnThreadInfo線程的run()方法先運(yùn)行完,然后Main類的System.out.println(returnThreadInfo.getThreadInfo())再運(yùn)行,這樣輸出的結(jié)就一定是期望的"Hello World!"了。這種通過(guò)調(diào)整線程優(yōu)先級(jí)的方法固然可以在某種程度上解決該問(wèn)題,但是線程爭(zhēng)用CPU運(yùn)行時(shí)間的原理卻決不僅僅只是優(yōu)先級(jí)高低的原因(優(yōu)先級(jí)高的線程并不意味著一定比優(yōu)先級(jí)低的線程先運(yùn)行,只是幾率要更大一些)。你并不希望ReturnThreadInfo線程9999次都比Main先運(yùn)行,卻在關(guān)鍵的一次在Main之后再運(yùn)行。因此下面給出兩種比較常見的獲取線程信息的方法:

        一、輪詢

        比較常見的一種解決方案是,讓線程類獲取方法在結(jié)果字段設(shè)置之前返回一個(gè)標(biāo)志值。然后主線程定時(shí)詢問(wèn)獲取方法,看是否返回了標(biāo)志之外的值。以下給出了具體的實(shí)現(xiàn)方法,該方法不斷測(cè)試str的值是否為"Hello",如果不為"Hello"才打印輸出它。例如:

      package threadtest1;

      /**

      *

      * @author shi mingxiang

      */

      public class Main{


      public Main() {

      }


      /**

      * @param args the command line arguments

      */

      public static void main(String[] args) {

      ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();

      returnThreadInfo.start();//創(chuàng)建并啟動(dòng)ReturnThreadInfo線程

      while(true){

      String str = returnThreadInfo.getThreadInfo();

      if(!str.equals("Hello")){

      System.out.println(returnThreadInfo.getThreadInfo());

      break;

      }

      }

      }

      }

        這種方案雖然能起到作用,但是它做了大量不需要做的工作。事實(shí)上,還有一種更簡(jiǎn)單有效的方法來(lái)解決這個(gè)問(wèn)題。

        二、回調(diào)

        輪詢方法的特點(diǎn)是主類Main不斷詢問(wèn)線程類是否結(jié)束,這實(shí)際上大量浪費(fèi)了運(yùn)行時(shí)間,特別是當(dāng)線程特別多的時(shí)候。因此如果反過(guò)來(lái)在線程結(jié)束時(shí),由線程自己告訴主類Main線程已經(jīng)結(jié)束,然后Main再獲取并輸出str的值,這樣就避免了輪詢方法所帶來(lái)的不必要的系統(tǒng)開銷問(wèn)題。

        在具體的實(shí)現(xiàn)過(guò)程中,線程可以在結(jié)束時(shí)通過(guò)調(diào)用主類中的一個(gè)方法來(lái)實(shí)現(xiàn)告知功能,這種方法叫做回調(diào)。這樣主類Main就可以在等待線程結(jié)束時(shí)休息,也就不會(huì)占用運(yùn)行線程的時(shí)間。下面是修改后的Main類:

      public class Main{

      public Main() {

      }


      /**

      * @param args the command line arguments

      */

      public static void main(String[] args) {

      // TODO code application logic here

      ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();

      returnThreadInfo.start();

      }


      public static void receiveStr(String str){

      System.out.println(str);

      }

      }

        相比于前面,我們?cè)贛ain類中添加了一個(gè)靜態(tài)方法receiveStr(String str),該方法是供線程結(jié)束之前調(diào)用,通過(guò)參數(shù)str將要返回的線程信息返回給Main類并輸出顯示出來(lái)。下面是修改后的ReturnThreadInfo類,該類在線程結(jié)束前回調(diào)了Main.receiveStr方法,通知線程已結(jié)束。

      package threadtest1;

      /**

      *

      * @author shi mingxiang

      */

      public class ReturnThreadInfo extends Thread {

      private String str;

      public ReturnThreadInfo() {

      this.str = "Hello";

      }

      public void run(){

      this.str = "Hello World!";

      Main.receiveStr(str); //回調(diào)receiveStr方法

      }

      }

        如果有很多個(gè)對(duì)象關(guān)心線程的返回的信息,線程可以保存一個(gè)回調(diào)對(duì)象列表。某個(gè)對(duì)象可以通過(guò)已經(jīng)定義的一個(gè)對(duì)象將自己添加到列表中,表示自己對(duì)這些信息的關(guān)注。如果有多個(gè)類的實(shí)例關(guān)心這些信息,也可以定義一個(gè)interface,在interface中聲名回調(diào)方法,然后這些類都實(shí)現(xiàn)這個(gè)接口。其實(shí)這是典型的java處理事件的方法,這么做可以使得回調(diào)更靈活,可以處理涉及更多線程、對(duì)象和類的情況。稍后會(huì)給出這種模仿事件處理模型的回調(diào)的實(shí)現(xiàn)方法。

      免費(fèi)預(yù)約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 午夜福利福利视频网 | 亚洲国产日韩在线 | 天天亚洲欧美日韩久久 | 中日韩国语视频在线观看免费 | 偷自拍亚洲综合在线 | 一本久久a久久精品vr综合夜夜 |