B-GangsteR B-GangsteR - 2 months ago 13
Android Question

Using Object.wait instead of Thread.sleep for time-synchronization

I have found this example in reliable source (https://developer.android.com/guide/components/services.html#CreatingStartedService) :

public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}


The question is: Why "sleeping" was implemented this way, and not like this:

endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
try {
Thread.sleep(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}


The suggested approach is more compact, and there is no any thread that can call 'notify' on this object. Anyway, even if there it was, the program will "go to sleep" again, if time limit was not expired. So what is hidden reason to write more complex and long code to achieve the same result?

I've seen this question Difference between wait() and sleep() , but it has no answer for my question.
I also have seen this Using Object.wait(millisec) to simulate sleep , but my question is more specific.

UPDATE



Can't believe that developer.android.com provides different code samples for different languages (in my case, for English and Russian). Maybe it just have not been updated yet..

See this screen-shot:
https://developer.android.com/guide/components/services.html#CreatingStartedService

Answer

Because they did it wrong.

There is no reason to implement that 5 second sleeping using Object.wait. Object.wait is used for synchronization and Thread.sleep for sleeping.

Synchronizing on this is another hint that it all is bad programming. You should avoid it in general unless you have a really good reason for it and in such case it should be documented, which is not the case.

Furthermore when I follow your link I see it this way in their page :

 /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // Normally we would do some work here, like download a file.
      // For our sample, we just sleep for 5 seconds.
      try {
          Thread.sleep(5000);
      } catch (InterruptedException e) {
          // Restore interrupt status.
          Thread.currentThread().interrupt();
      }
  }
}

So maybe they have realized of their mistake and corrected it.

Take notice of how in that code interrupts are properly handled rather than discarded as in the two pieces of code in the original question.

Comments