Alternative to Thread.sleep() for performance?

Viewed 780

I am doing a function in my Spring Boot application where in a REST request, I have to wait for a variable from the DB to have 'x' value and then return the response to the client.

I did it with Thread.sleep() in a while, but is it the best way to do it in terms of performance?

Code with Thread.sleep:

   while(!peticionTmp.isRealizada()) {
        entityManager.clear();
        peticionTmp = peticionesRepository.findById(peticion_id);
        Thread.sleep(3000);
        System.out.println("Iteración! --> " + peticionTmp);
    }
    
    return peticionTmp.isRealizada();

I saw what could be done with this:

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor ();
     scheduler.schedule (() -> {
         / *
          * define work to be done inside this lambda
          * /
     }, diffTime, TimeUnit.MILLISECONDS);

But I don't know how to implement it in the while.

The client sends a request, the spring boot application saves the request to the DB, now another program looks at the DB in search of requests, makes the service that contain the request and changes a field in the database of that request, the spring boot when it sees that it has been changed that field, I return the response to the client ...

1 Answers

As others have already pointed out, you have a very wrong system design in your hands, so you most likely have far bigger problems than performance.

Now, if you really must improve the performance of your existing brain-damaged system, then first of all you need to define performance.

What is performance for you? Response time from the point of view of the client? Number of clock cycles wasted on the server? Number of simultaneous clients that can be served?

Your mind-bogglingly long timeout of 3 entire seconds seems to indicate that you perceive performance as clock cycles wasted on the server. We usually choose very long polling periods when we want to greatly space out the moments of polling, so as to reduce the amount of work done per second.

But that was probably not your intention. What you are probably concerned about is response time from the point of view of the client, since a timeout of 3 seconds means that the client will always wait at least 3 seconds, and certainly a multiple of 3 seconds. If you want to improve that, then the solution is simple: instead of Thread.sleep(3000) do Thread.sleep(300) or even Thread.sleep(30). Now, that will increase the number of clock cycles wasted on the server; would that be a problem? We don't know, because you have not defined what performance means for you. But what we do know is that you cannot have everything: a brain-damaged system design will have to make compromises.

Adding information from the comments:

To fix this situation the first step is to give the server definitive knowledge of when the processing is complete, instead of having the server do polling to determine that. There are two approaches to this:

  1. Have the server do the processing instead of an external application.
  2. Have the server launch an external application to do the processing, and wait for that application to terminate, so that as soon as the external application terminates, the server knows that the processing is done.

Then, you have a number of alternatives as far as the response to the client is concerned:

  1. The server can keep the request waiting while the work is being done, and return a result at the end. You are currently accomplishing this with Thread.Sleep(), but as I have explained above, this needs to go away, and to be replaced with the actual processing. If the processing must be done by an external application, then it will be replaced by Process.WaitFor()
  2. The server can return a result saying "working on it" and then the client can keep calling the same or another API to poll for the results.
  3. The server can make use of spring boot's DeferredResult.

If the client was a web browser instead of a REST client, then you would have two additional options:

  1. The server can return a result saying "working on it" and then the client can use Ajax to receive notification that the work is done.
  2. The server can return a result saying "working on it; please refresh the page to see if it is ready."
Related