1

I am trying to call a method multiple times every 60 seconds until a success response from the method which actually calls a rest end point on a different service. As of now I am using do while loop and using

Thread.sleep(60000);

to make the main thread wait 60 seconds which I feel is not the ideal way due to concurrency issues.

I came across the CountDownLatch method using

CountDownLatch latch = new CountDownLatch(1);
boolean processingCompleteWithin60Second = latch.await(60, TimeUnit.SECONDS);

@Override
public void run(){

    String processStat = null;
    try {
        status = getStat(processStatId);
        if("SUCCEEDED".equals(processStat))
        {
            latch.countDown();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }   
}

I have the run method in a different class which implements runnable. Not able to get this working. Any idea what is wrong?

Upen
  • 1,388
  • 1
  • 22
  • 49
  • why are you calling await twice? What do you mean be 'not able to get this working?' – bmargulies Jul 13 '17 at 17:37
  • Sorry for the mistake. I have corrected it. The problem here I am facing is that, I am calling the method from the Runnable class and not able to figure out how to pass the success/error response from the runnable class to the main thread. – Upen Jul 13 '17 at 17:41

2 Answers2

2

You could use a CompletableFuture instead of CountDownLatch to return the result:

CompletableFuture<String> future = new CompletableFuture<>();

invokeYourLogicInAnotherThread(future);

String result = future.get(); // this blocks

And in another thread (possibly in a loop):

@Override
public void run() {

    String processStat = null;
    try {
        status = getStat(processStatId);
        if("SUCCEEDED".equals(processStat))
        {
            future.complete(processStat);
        }
    } catch (Exception e) {
        future.completeExceptionally(e);
    }   
}

future.get() will block until something is submitted via complete() method and return the submitted value, or it will throw the exception supplied via completeExceptionally() wrapped in an ExecutionException.

There is also get() version with timeout limit:

String result = future.get(60, TimeUnit.SECONDS);
Roman Puchkovskiy
  • 11,415
  • 5
  • 36
  • 72
  • The project is running on Java 7. Wont be able to make use of CompletableFuture. – Upen Jul 13 '17 at 18:26
  • Is using Guava an option? I mean its `ListenableFuture`: https://google.github.io/guava/releases/21.0/api/docs/com/google/common/util/concurrent/ListenableFuture.html – Roman Puchkovskiy Jul 13 '17 at 19:06
0

Finally got it to work using Executor Framework.

            final int[] value = new int[1];
            pollExecutor.scheduleWithFixedDelay(new Runnable() {

                Map<String, String> statMap = null;

                @Override
                public void run() {

                    try {
                        statMap = coldService.doPoll(id);
                    } catch (Exception e) {

                    }
                    if (statMap != null) {
                        for (Map.Entry<String, String> entry : statMap
                                .entrySet()) {
                            if ("failed".equals(entry.getValue())) {
                                value[0] = 2;

                                pollExecutor.shutdown();
                            }
                        }
                    }
                }

            }, 0, 5, TimeUnit.MINUTES);
            try {
                pollExecutor.awaitTermination(40, TimeUnit.MINUTES);
            } catch (InterruptedException e) {

            }
Upen
  • 1,388
  • 1
  • 22
  • 49