2012-02-23 76 views
3

我有一個需要等待的時間一些未知量的應用程序。它必須等到服務器填充完成幾個數據字段。最好的方法等待在Java中

服務器的API提供了我的方式來請求數據,很容易...

服務器的API還提供了一種接收我的數據傳回,一次一個字段。它沒有告訴我什麼時候所有的字段都完成了填充。

什麼是最有效的方式,等到我的要求完成由服務器處理?下面是一些僞代碼:

public class ServerRequestMethods { 
    public void requestData(); 
} 

public interface ServerDeliveryMethods { 
    public void receiveData(String field, int value); 
} 

public class MyApp extends ServerRequestMethods implements ServerDeliveryMethods { 
    //store data fields and their respective values 
    public Hashtable<String, Integer> myData;  

    //implement required ServerDeliveryMethods 
    public void receiveData(String field, int value) { 
     myData.put(field, value);  
    } 

    public static void main(String[] args) { 
     this.requestData(); 

     // Now I have to wait for all of the fields to be populated, 
     // so that I can decide what to do next. 

     decideWhatToDoNext(); 
     doIt(); 
    } 
} 

我不得不等待,直到服務器完成填充我的數據字段,並且服務器沒有讓我知道請求完成時。所以我必須繼續檢查我的請求是否已完成處理。什麼是最有效的方法來做到這一點?

的wait()和notify(),與守衛while循環,檢查的方法,如果我擁有所有必需的值然而,每一個我被通知喚醒時間()?

觀察和觀察的,與每一次我Observer.Update()檢查,如果我有所有所需的值還沒有一個方法被調用?

什麼是最好的方法?謝謝。

+0

「服務器的API還提供了一種方法來接收我的數據,一次一個字段」。這是如何運作的?呼叫是否等待該特定字段被填充或是否立即返回,有無字段數據? – 2012-02-23 11:21:53

+0

@四十二爲了接收消息,服務器要求我在psuedocode中實現接口「ServerDeliveryMethods」。因此,當服務器向我發送數據時,它會調用此方法,並將數據填入參數中。 – rallison 2012-02-23 11:54:00

+0

問題是 - 您的客戶端應用程序認爲「完成」是什麼?不管你可能需要一個單獨的線程來與服務器進行通信,還有一個信號量(概念,而不是類)在你的主線程中等待,這會保護'decideWhatToDoNext()'方法。 – Perception 2012-02-23 11:55:30

回答

5

如果我理解你的權利,其他的一些線程電話receiveDataMyApp填充數據。如果這是正確的,那麼這裏是你如何做到這一點:

  1. 你睡這樣的:

    do { 
        this.wait(someSmallTime); //We are aquiring a monitor on "this" object, so it would require a notification. You should put some time (like 100msec maybe) to prevent very rare but still possible deadlock, when notification came before this.wait was called. 
    } while (!allFieldsAreFilled()); 
    
  2. receiveData的應該做一個notify召喚,unpausewait呼叫你的事。例如像這樣:

    myData.put(field, value); 
    this.notify(); 
    
  3. 兩個塊將需要在this對象進行「同步」,以便能夠將收購它的顯示器(這是需要wait)。您需要將方法聲明爲「已同步」,或者將各個塊放在synchronized(this) {...}塊內。

+0

服務器調用receiveData方法將字段及其各自的值發回給我,一次一個。所以有60個字段,因此服務器調用這個方法60次。所以我認爲這就是你所說的,因爲服務器正在使用一個Java Socket,我猜它就像是「一些其他線程」。是? – rallison 2012-02-23 12:13:11

+0

基本上,服務器無法簡單地「調用receiveData」。我猜你正在使用某種框架來完成這項任務。該框架接受服務器數據並調用您的方法。無論如何,這並沒有改變。從你的描述來看,你確實有兩個獨立的線程,因此這種方法是「等待」這些數據的最簡單的方法。 – bezmax 2012-02-23 12:16:27

+0

我忽略了一些細節,試圖簡化我的問題,但我明白了你的觀點。技術上,ServerRequestMethods還提供了一個構造函數,它將ServerDeliveryMethods作爲其參數。然後在MyApp構造函數中初始化一個實例變量:myServerRequestMethodsInstance = new ServerRequestMethods(this)。然後在主要的實際調用是myServerRequestMethodsInstance.requestData()。所以請求/接收類是鏈接的,服務器實際上只是調用receiveData,儘管我不確定細節。但我認爲這仍然沒有改變。謝謝! – rallison 2012-02-23 12:33:01

1

我認爲最有效的方法是等待和通知。您可以使用wait()將線程設置爲睡眠。您可以從另一個線程喚醒線程,例如你的服務器用notify()來喚醒。 wait()是一種阻止方法,您不必輪詢任何內容。您也可以使用靜態方法Thread.sleep(milliseconds)等待一段時間。如果你將睡眠時間設置爲無盡的循環檢查,並持續等待一段時間,那麼你也可以等待。

我喜歡wait()notify(),其最有效的。

-2

看起來很多人一直有這個問題(包括我自己),但我找到了一個簡單而時尚的解決方案。使用此方法:

public static void delay(int time) { 
    long endTime = System.currentTimeMillis() + time; 
    while (System.currentTimeMillis() < endTime) 
    { 
     // do nothing 
    } 
} 

此獲取當前時間,並設置結束時間(當前時間+等待時間),並等待,直到當前的時間打的結束時間。

+0

這是一個超級低效的解決方案,所以不要那樣做 – gyurix 2016-12-11 18:01:32

0

很老的問題,但我找了類似的問題,並找到了解決辦法。
起初,開發者不應該創建一個永遠等待的線程。如果您使用'while'循環,則必須創建'退出條件'。另外,等待'InterruptedException'很棘手。如果另一個線程沒有調用yourThread.interrupt(),你會等到程序真正結束。 我用java.util.concurrent.CountDownLatch因此,在短期:

/*as field*/ 
CountDownLatch semaphore = new CountDownLatch(1); 

/*waiting code*/ 
boolean timeout = !semaphore.await(10, TimeUnit.SECONDS); 

/*releasing code*/ 
semaphore.countDown(); 

至於結果,「等待代碼」線程等待某些另一個線程調用「釋放代碼」或將「超時」。如果您想等待填充10個字段,則使用'new CountDownLatch(10)'。
這個原理與'java.util.concurrent.Semaphore'類似,但信號量更適合訪問鎖定,事實上並非如此。