2012-02-23 187 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'类似,但信号量更适合访问锁定,事实上并非如此。