4

I have a async function that calls other async function. In Java, how to wait on untill the async call completes(including any nested async calls in it).

I already Future callable But no luck.

Sample code:

void asyncMehodA(){ }

void asyncMethodB() {
asyncMehodA();
}

I tried the Future callable in the following way:

final Callable<Void> callable1 = new Callable<Void>() {
            @Override
            public Void call() {
                asyncMethodB();
                return null;
            }
        };
final Future<Void> callableFuture = mExecutor.submit(callable1);

    try {
            callableFuture.get();

        } catch (final InterruptedException | ExecutionException e) {}

hoping that the get function will block the execusion untill the async return. But seems the get function will fire the async call and reurn null. not waiting for the asycn to complete its execusion. I added log statements in the verified the same. Please correct me if my understanding is wrong. suggest any other concepts that can aid me.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Sandy K
  • 65
  • 1
  • 1
  • 8

2 Answers2

1

Here is an example using CountDownLatch.

package chapter13;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class BST {

    public static void main(String[] args) throws InterruptedException {

        final CountDownLatch latch = new CountDownLatch(1);
        final ExecutorService executorService = Executors.newCachedThreadPool();

        Runnable runnableA = () -> {
            System.out.println("Runnable A");
            latch.countDown();
            System.out.println("Runnable A finished");
        };

        Runnable runnableB = () -> {
            System.out.println("Runnable B");
            executorService.submit(runnableA);
            try {
                System.out.println("Runnable B waiting for A to complete");
                latch.await();
                System.out.println("Runnable B finished");
            } catch (InterruptedException e) {
                System.out.println("Thread interrupted");
                Thread.currentThread().interrupt();
            }
        };

        executorService.submit(runnableB);

        Thread.sleep(10);

        shutDown(executorService);
    }

    private static void shutDown(ExecutorService executorService) {

        executorService.shutdown();

        try {
            if (!executorService.awaitTermination(1, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
        }

    }


}

I use Thread.sleep() method to sleep the main thread, because shuting down the pool immediately after task B was submitted, might cause the pool to stop accepting new tasks before task A is submitted by task B.

Michał Krzywański
  • 15,659
  • 4
  • 36
  • 63
0

One way would be to use a java locking method. An example:

private AtomicBoolean   processed = new AtomicBoolean(true) ;
private String          result = null ;

public String doAndWait()
{
    synchronized(processed) {
        doSomethingAsync() ;
        processed.wait();
    }
    return result ;
}

public void doSomethingAsync()
{
    ...
    result="OK";
    synchronized(processed) {
        processed.notify();
    }
}
Marvin
  • 598
  • 5
  • 14
  • Thanks @Marvin for sharing your thoughts. But once I fire the async call before setting result to "OK", And then continue with execusion. We are not waiting for the async call return. I am assuming the three dots in your solutuon is firing async calls. So in that case, We are not totally synchronized the async call. – Sandy K Mar 31 '19 at 21:46
  • Aha, I see, if you have many async to execute, you can always use wait/notify to get notification about async process finish. (You can also use listeners). Unfortunately I don't know your practical need to suggest :) – Marvin Mar 31 '19 at 23:36