简体   繁体   English

在Java中等待的最佳方式

[英]Best way to wait in Java

I have an app that needs to wait for some unknown amount of time. 我有一个需要等待一段时间的应用程序。 It must wait until several data fields are finished being populated by a server. 它必须等到服务器填充几个数据字段。

The server's API provides me a way to request data, easy enough... 服务器的API为我提供了一种请求数据的方法,很简单......

The server's API also provides a way to receive my data back, one field at a time. 服务器的API还提供了一种接收我的数据的方法,一次一个字段。 It does not tell me when all of the fields are finished being populated. 它并没有告诉我何时完成所有字段的填充。

What is the most efficient way to wait until my request is finished being processed by the server? 在我的请求完成服务器处理之前,最有效的方法是什么? Here's some pseudocode: 这是一些伪代码:

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();
    }
}

I have to wait until the server is finished populating my data fields, and the server doesn't let me know when the request is complete. 我必须等到服务器完成填充我的数据字段,服务器不会让我知道请求何时完成。 So I must keep checking whether or not my request has finished processing. 所以我必须继续检查我的请求是否已经完成处理。 What is the most efficient way to do this? 最有效的方法是什么?

wait() and notify(), with a method guarding the while loop that checks if I have all of the required values yet every time I'm woken up by notify()? wait()和notify(),一个守护while循环的方法,每当我被notify()唤醒时,检查我是否已经拥有了所有必需的值?

Observer and Observable, with a method that checks if I have the all the required values yet every time my Observer.Update() is called? Observer和Observable,有一个方法可以在每次调用Observer.Update()时检查是否具有所有必需的值?

What's the best approach? 什么是最好的方法? Thanks. 谢谢。

If I understood you right, some other thread calls receiveData on your MyApp to fill the data. 如果我理解正确,其他一些线程会MyApp上调用receiveData来填充数据。 If that's right, then here's how you do it: 如果这是对的,那么这就是你如何做到的:

  1. You sleep like this: 你像这样睡觉:

     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 should make a notify call, to unpause that wait call of yours. receiveData应该进行notify呼叫,以unpause您的wait呼叫。 For example like this: 例如这样:

     myData.put(field, value); this.notify(); 
  3. Both blocks will need to be "synchronized" on this object to be able to aquire it's monitor (that's needed for wait ). 两个块都需要在this对象上“同步”才能获取它的监视器( wait所需的)。 You need to either declare the methods as "synchronized", or put the respective blocks inside synchronized(this) {...} block. 您需要将方法声明为“synchronized”,或将相应的块放在synchronized(this) {...}块中。

i think the most efficient method is with wait and notify. 我认为最有效的方法是使用wait和notify。 You can set a Thread into sleep with wait() . 您可以使用wait()将Thread设置为sleep。 You can wake up the Thread from another one, eg your server with notify() to wake up. 您可以从另一个唤醒线程,例如您的服务器使用notify()唤醒。 wait() is a blocking method, you dont have to poll anything. wait()是一种阻塞方法,你不必轮询任何东西。 You can also use the static method Thread.sleep(milliseconds) to wait for a time. 您还可以使用静态方法Thread.sleep(milliseconds)来等待一段时间。 If you put sleep into a endless while loop checking for a condition with a continusly wait time, youll wait also. 如果你把睡眠放入无休止的循环中检查一个连续等待时间的条件,你也会等待。

I prefer wait() and notify() , its most efficient at all. 我更喜欢wait()notify() ,它最有效率。

Pretty old question, but I looked for similar problem and found a solution. 很老的问题,但我寻找类似的问题,并找到了解决方案。
At first, developer should never create a thread that will wait forever. 起初,开发人员永远不应该创建一个永远等待的线程。 You really have to create 'exit condition' if you are using 'while' cycle. 如果你正在使用'while'循环,你真的必须创建'退出条件'。 Also, waiting for 'InterruptedException' is tricky. 此外,等待'InterruptedException'是棘手的。 If another thread doesn't call yourThread.interrupt() you'll wait until program truly ends. 如果另一个线程没有调用yourThread.interrupt(),你将等到程序真正结束。 I used java.util.concurrent.CountDownLatch so in short: 我简单地使用了java.util.concurrent.CountDownLatch:

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

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

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

As result, 'waiting code' thread will wait until some another Thread calls 'releasing code' or will "timeout". 结果,'等待代码'线程将等待另一个线程调用'释放代码'或将“超时”。 If you want to wait for 10 fields to be populated, then use 'new CountDownLatch(10)'. 如果要等待填充10个字段,请使用“new CountDownLatch(10)”。
This principle is similar for 'java.util.concurrent.Semaphore' but semaphore is better for access locking and that isn't your case, indeed. 这个原则与'java.util.concurrent.Semaphore'类似,但信号量更适合访问锁定,事实并非如此。

It seems like many people have been having trouble with this (myself included) but I have found an easy and sleek solution. 似乎很多人都遇到了麻烦(包括我自己),但我找到了一个简单而时尚的解决方案。 Use this method: 使用此方法:

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

This gets the current time and sets an end time (current time + time to wait) and waits until the current time hits the end time. 这将获取当前时间并设置结束时间(当前时间+等待时间)并等待当前时间到达结束时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM