簡體   English   中英

在Java中等待的最佳方式

[英]Best way to wait in 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循環的方法,每當我被notify()喚醒時,檢查我是否已經擁有了所有必需的值?

Observer和Observable,有一個方法可以在每次調用Observer.Update()時檢查是否具有所有必需的值?

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

如果我理解正確,其他一些線程會MyApp上調用receiveData來填充數據。 如果這是對的,那么這就是你如何做到的:

  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呼叫,以unpause您的wait呼叫。 例如這樣:

     myData.put(field, value); this.notify(); 
  3. 兩個塊都需要在this對象上“同步”才能獲取它的監視器( wait所需的)。 您需要將方法聲明為“synchronized”,或將相應的塊放在synchronized(this) {...}塊中。

我認為最有效的方法是使用wait和notify。 您可以使用wait()將Thread設置為sleep。 您可以從另一個喚醒線程,例如您的服務器使用notify()喚醒。 wait()是一種阻塞方法,你不必輪詢任何東西。 您還可以使用靜態方法Thread.sleep(milliseconds)來等待一段時間。 如果你把睡眠放入無休止的循環中檢查一個連續等待時間的條件,你也會等待。

我更喜歡wait()notify() ,它最有效率。

很老的問題,但我尋找類似的問題,並找到了解決方案。
起初,開發人員永遠不應該創建一個永遠等待的線程。 如果你正在使用'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'類似,但信號量更適合訪問鎖定,事實並非如此。

似乎很多人都遇到了麻煩(包括我自己),但我找到了一個簡單而時尚的解決方案。 使用此方法:

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

這將獲取當前時間並設置結束時間(當前時間+等待時間)並等待當前時間到達結束時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM