熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java 線程缺陷和副作用的解決辦法(2)

2013-11-23 19:59:16  來源: Java高級技術 

  表A: 演示高級線程方法的偽代碼

  class ProdCons
  {
   class List
   {
    public synchronized boolean add(Object o)
    {}
    public synchronized boleanremove (Object o)
    {}
   }
   List data = new List();
   ProdThread producer = null;
   ConsThread consumer = null;
   ProdCons()
   {
    producer = new ProdThread(this);
    consumer = new ConsThread(this);
    producerstart();
    consumerstart();
   }
  }
  
  消費者和生產者的類請見表B和表C

  表B: Class ConsThread

  class ConsThread extends Thread
  {
   ProdCons parent;
   ConsThread(ProdCons parent)
   {
    thisparent = parent;
   }
   public synchronized void canConsume()
   {
    notify();
   }
   public void run()
   {
    boolean consumed;
    do
    {
     synchronized(this)
     {
      try { wait();
     }
     catch (Exception e) { ; }
    }  
    do
    {
     String str = (String)parentlistremove();
     if ( null == str)
     {
      consumed = false;
      break;
     }
     consumed = true;
     Systemoutprintln(Consumer=>consumed + str);
    }
    while ( true );
   }
   while (consumed);
  }
 
  表C: Class ProdThread

  class ProdThread extends Thread
  {
   ProdCons parent;
   ProdThread(ProdCons parent)
   {
    thisparent = parent;
   }
   public void run()
   {
    for ( int i = ; i < ; i++)
    {
     String str = new String(ImAString + i);
     Systemoutprintln(Producer produced + str);
     parentlistadd(str);
     parentconsumercanConsume();
    }
    parentconsumercanConsume();
   }
  }

  注意notify和wait兩個API都必須位於同步化(synchronized)的方法中或者代碼塊中!

  線程和Sun JDK

  線程提供了一項很有價值的服務極大地增強了Java程序設計語言的功能然而目前的線程實現的確存在一些問題這些問題的存在使得Sun JDK 中線程的stop suspend和resume方法導致人們的批評

  如果我們回到上面的生產者/消費者例子我們就可以更好地理解這個問題首先我們看看死鎖當運行一個applet小程序時在通常的情況下兩個線程運行時相安無事但是但用戶點擊到另外一個網頁時問題出現了如果生產者正在添加一個項目到列表中最壞的情況就是消費者線程被阻塞假定小程序正在創建一個對象此時突然被掛起(suspended)其他的小程序就不能再對該數據進行更新盡管出現這樣的機會不多它們的確存在有時會引起問題

  線程的第二個問題有關不一致的問題再來看一下生產者/消費者的例子不難想象如果生產者線程在添加項目的過程中遇到被中止的情況可能會造成列表狀態不一致如果我們全面檢查現有的Java小程序的個數就不難發現問題所在

  處理這個不一致的問題的最簡單的方法就是派生一個新的線程類該線程類具有如下功能通過一個方法的調用可以改變其狀態表D就定義了這樣的一個類MyThread類可以被掛起和重新執行而無需擔心MyThread類的資源會崩潰MyThread類中的方法 changeState用於暗示應該暫停停止或者重新執行線程而不同於以往的停止或者暫停線程可以向線程發出請求要求線程在合適的時候處理該請求而不是強制處理該請求因而無需向線程發出停止命令

  表D: Class MyThread

  public class MyThread extends Thread
  {
   //States the thread can be in
   static final int STATE_RUNNING = ;
   static final int STATE_STOP = ;
   static final int STATE_SUSPEND = ;
   private int currentState = STATE_RUNNING;
   // The public method changeState allows
   // another process to poke at that hread
   // and tell it to do something when it
   // next gets a chance
   public final synchronized void
   changeState(int newState)
   {
    currentState = newState;
    if (STATE_RUNNING == currentState)
    notify();
    // Must have been suspended
   }
   private synchronized boolean currentState()
   {
    // If we where asked to suspend
    // just hang out until we are
    // asked to either run or stop
    while ( STATE_SUSPEND == currentState)
    {
     try{ wait(); }
     catch (Exception e) {};
    }
    if ( STATE_STOP == currentState )
    return false;
    else
    return true;
   }
   public void run()
   {
    do
    {
     if (currentState() == false)
     return; // Done
     // Perform some work
    }   
    while (true);
   }
  }

  MyThread類的用戶可以重載run方法然而用戶需要檢查是否有另外的類請求線程改變狀態在JDK 中對線程的運行機制所做的改變是問題的症結所在線程在運行時是否出現不一致在線程關閉後是否放棄所占用的資源線程的運行是否正常這些工作都是要開發者自己來確保完成了

  結論

  線程功能強大而使用復雜每位Java開發者可以在很多應用場合用到線程本文中我們檢查了線程的一些副作用以及線程的一些高級用法隨著Sun JDK 的推出開發者們將被迫對其編寫的線程對系統和其他進程的作用過程考慮得更加周到最終對於線程及其相關知識的正確理解將會有助於聰明的開發者設計出更加健壯的應用程序


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27773.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.