在Java中等待的最佳方式

时间:2012-02-23 11:17:14

标签: java wait notify

我有一个需要等待一段时间的应用程序。它必须等到服务器填充了几个数据字段。

服务器的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()时检查是否具有所有必需的值?

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

5 个答案:

答案 0 :(得分:5)

如果我理解正确,其他主题会在receiveData上调用MyApp来填充数据。如果这是对的,那么这就是你如何做到的:

  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应拨打notifyunpause wait来电。myData.put(field, value); this.notify(); 例如:

    this
  3. 两个块都需要在wait对象上“同步”才能获取它的监视器(synchronized(this) {...}所需的)。您需要将方法声明为“synchronized”,或将相应的块放在{{1}}块中。

答案 1 :(得分:3)

答案 2 :(得分:1)

我认为最有效的方法是使用wait和notify。您可以使用wait()将线程设置为休眠状态。你可以从另一个中唤醒线程,例如唤醒notify()的服务器。 wait()是一种阻止方法,您不必轮询任何内容。您还可以使用静态方法Thread.sleep(milliseconds)等待一段时间。如果你把睡眠放入无休止的循环中检查一个连续等待时间的条件,你也会等待。

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

答案 3 :(得分:0)

相当古老的问题,但我寻找类似的问题并找到了解决方案 起初,开发人员永远不应该创建一个永远等待的线程。你真的必须创建退出条件&#39;如果您正在使用&#39;而#39;周期。此外,等待“InterruptedException”#39;很棘手如果另一个线程没有调用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();

结果,等待代码&#39;线程将等待另一个线程调用&#39;释放代码&#39;或将&#34;超时&#34;。如果您要等待填充10个字段,请使用新的CountDownLatch(10)&#39;。
这个原则类似于&#39; java.util.concurrent.Semaphore&#39;但信号量更适合访问锁定,事实上并非如此。

答案 4 :(得分:-2)

似乎很多人都遇到了麻烦(包括我自己),但我找到了一个简单而时尚的解决方案。使用此方法:

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

获取当前时间并设置结束时间(当前时间+等待时间)并等待当前时间到达结束时间。

相关问题