從java線程中獲得運算結果

來源:互聯網
上載者:User
 java的線程是由Thread來實現的,一般我們建立線程進行一個複雜的運算,然後在主線程中對運算結果進行處理,但是Thread的run函數並沒有傳回值,那麼我們運算出結果後,怎麼通知其它線程呢,本文講述了幾種返回資訊的方法。
 一。java線程的建立
 
 要建立線程有兩種辦法,一是繼承Thread類,二是實現Runnable,然後將其傳遞給一個Thread的建構函式,執行個體如下(假設我們要在一個線程中計算1到10000的和):
 1。繼承Thread:
 public class AddThread extends Thread {
 public void run() {
  int result = 0;
  for(int i = 1; i <= 10000; i++) {
   result += i;
  }
 }
 }
 運行AddThread:
  AddThread thread = new AddThread();
  thread.start();
 2。實現介面Runnable:
 public class Add implements Runnable {
 public void run() {
  int result = 0;
  for(int i = 1; i <= 10000; i++) {
   result += i;
  }
 }
 }
 運行該線程: Thread thread = new Thread(new Add());
    thread.start();
 二、返回運算結果的方法
 
 現在我們啟動這個加法線程後,需要從這個線程中得到運算的結果,例如我們要在主線程中對運算結果進行顯示。那麼我們怎麼實現呢?下面就講述幾種常見的方法,注意其中有一些是錯誤的方法
 1。使用get方法(錯誤的)
 我們可以在AddThread中加入一個getResult函數得到運算結果:
 public class AddThread extends Thread {
  private int result = 0;
  public void run() {
   for(int i = 0; i <= 10000; i++)
    result += i;
  }
  public int getResult() {
   return result;
  }
 }
 
 /** 得到運算結果並顯示在螢幕上
 */
 public class Test {
  public static void main(String[] args) {
   AddThread thread = new AddThread();
   thread.start();
   System.out.println("result is " + thread.getResult());
  }
 }
 
 得到的結果是: result is 0
 
 因為這裡主線程和addThread線程是同時運行,AddThread的運算還沒有完成(甚至可能還沒有開始),主線程就開始輸出運算結果了,所以這種方式是錯誤的。
 
 2。查詢法(可行,但效率極低)
  
 第二種方法是使用一個變數hasDone來表示運算是否完成,如果hasDone為false的時候表示運算尚未完成,否則表示運算已經完成。主線程不斷查詢這個變數,如果發現運算尚未完成,則進入迴圈等待,否則輸出運算結果。
   public class AddThread extends Thread {
     private int result = 0;
     private boolean hasDone = false;
     public void run() {
      for(int i = 0; i <= 10000; i++)
    result += i;
   hasDone = true;
     }
    
     public boolean hasDone() {
      return hasDone;
     }
    
     public int getResult() {
      return result;
     }
   }
 
    public class Test {
         public static void main(String[] args) {
           AddThread thread = new AddThread();
           thread.start();
           file://如果運算沒有完成,則迴圈等待
           while (!thread.hasDone()) {
  try {
   Thread.sleep(100);
  }
  catch (InterruptedException ex) {
  }
           }
           if (thread.hasDone())
  System.out.println("result is " + thread.getResult());
      
         }
      
    }
    結果顯示: result is 50005000
   
   
 主線程中迴圈查詢運算的狀態,如果運算沒有完成,則主線程sleep100毫秒,然後繼續查詢,這種方式雖然可行,但由於主線程迴圈查詢,消耗了大量的CPU時間,因此效率很低。
   
 3。wait/notify方式(較好)
 第三種方法使用wait/notify的形式,當運算沒有結束的時候,主線程進入睡眠狀態,這時它不佔用CPU,因此效率較高。
 
 public class AddThread
    extends Thread {
    file://在這個object上wait
    private Object lock;
    private int result = 0;
    private boolean hasDone = false;
 
    public AddThread(Object lock) {
      this.lock = lock;
    }
 
    public void run() {
      for (int i = 0; i <= 10000; i++)
        result += i;
      file://運算結束,通知等待的線程
      synchronized(lock) {
        hasDone = true;
        lock.notifyAll();
      }
    }
 
    public boolean hasDone() {
      return hasDone;
    }
 
    public int getResult() {
      return result;
    }
 }
 
 file://主線程
  public class Test {
         public static void main(String[] args) {
           Object lock = new Object();
           AddThread thread = new AddThread(lock);
           thread.start();
           synchronized(lock) {
  while (!thread.hasDone()) {
   try {
     file://當運算沒有結束,主線程進入睡眠狀態,當addThread執行notifyAll時,會喚醒主線程
     lock.wait();
   }
   catch (InterruptedException ex) {
   }
  }
           }
           if (thread.hasDone())
  System.out.println("result is " + thread.getResult());
         }
       }
      
 4。使用callback(較好)
 
 我覺得這是最好的一種方式,當運算完成後,AddThread自動調用結果處理類。將其擴充可以成為使多個listener對結果進行處理,這裡用到了Observer模式,這種方法很簡單,不需要考慮同步機制,具體實現如下:
 file://對結果進行處理的介面
 public interface ResultProcessor {
  public void process(int result);
 }
 
 public class AddThread extends Thread {
  private ResultProcessor processor;
 
  public AddThread(ResultProcessor processor) {
   this.processor = processor;
  }
 
  public void run() {
   int result = 0;
   for(int i = 0; i <= 10000; i++) {
    result += i;
   }
   file://對結果進行處理
   processor.process(result);
  }
 }
 public class Test implements ResultProcessor {
  public void process(int result) {
   System.out.println("result is " + result);
  }
 
  public static void main(String[] args) {
   Test test = new Test();
   AddThread thread = new AddThread(test);
   thread.start();
  }
 }
 結果顯示: result is 50005000
 
 代碼如上面,AddThread的建構函式傳進一個結果處理類,當運算完成時,自動調用這個類的處理函數對結果進行處理。比較起來,我覺得這種方法最好。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.