1

I am creating 10 threads and adding 2 kinds of jobs to them as follows.

public class ParallelAdder {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executor = Executors.newFixedThreadPool(10);
            List<Future<Integer>> list = new ArrayList<Future<Integer>>();
            for (int i = 0; i < 10; i++) {
                Future<Integer> future;
                if (i % 2 == 0) {
                    future = executor.submit(new Call1());
                } else {
                    future = executor.submit(new Call2());
                }

                list.add(future);

            }

            for(Future<Integer> fut : list) {
                System.out.println("From future is "+fut.get());
            }
        }
    }

class Call1 implements Callable<Integer> {
    public Integer call() throws Exception {
        System.out.println("Calling 1");
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 10;
    }

}

class Call2 implements Callable<Integer> {
    public Integer call() throws Exception {
        System.out.println("Calling 2");
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 20;
    }

}

Call2 job returns faster as compared to Call1. In my future list, I want the result of a job as soon as it completes. It should not depend on all others job to be done.
Here Call2 return is waiting for Call1. How to solve this?

1 Answer 1

1

The problem is that you're waiting by calling the blocking get here:

for(Future<Integer> fut : list) {
    System.out.println("From future is "+fut.get());
}

To solve this, you need to use reactive code. You could use the completable future API, which is designed for declarative reactive Future-like API:

ExecutorService executor = Executors.newFixedThreadPool(10);

Supplier<Integer> call1Supplier = () -> {
    System.out.println("Calling 1");
    try {
        Thread.sleep(100000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return 10;
};

Supplier<Integer> call2Supplier = () -> {
    System.out.println("Calling 1");
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return 10;
};

Then that can be submitted to the same executor service, but using the reactive CompletableFuture that has support for callback-like objects.

List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) {
        CompletableFuture<Void> future = 
                CompletableFuture.supplyAsync(call1Supplier, executor)
                .thenAccept(number -> System.out.println("From future is " + number));
        futures.add(future);
    } else {
        CompletableFuture<Void> future = 
                CompletableFuture.supplyAsync(call2Supplier, executor)
                .thenAccept(number -> System.out.println("From future is " + number));
        futures.add(future);
    }
}

The following is just to make sure that the current thread doesn't exit before all async tasks have completed. But if it's a long-running application, such as a server, this may be unnecessary

for (CompletableFuture<Void> future : futures) {
    future.join();
}

Note that I inlined the code from Call1 and Call2 as the Callable implementation isn't necessary. But it's still a good idea to keep it in a separate class (unless the function objects are just OK).

3
  • Thanks!. But if I remove future.join(); then also it is working fine
    – js_248
    Commented May 26, 2018 at 15:25
  • @oxy_js Oh yes it will still probably work. I've just edited it slightly, and commented that it's not necessary if you're calling it from a long-running application, such as a server. It's just to watch out if you're running it from main, because the main method may end up terminating the app, thus causing the VM to exit before the asynchronous tasks finish running.
    – ernest_k
    Commented May 26, 2018 at 15:28
  • Now I got it.Thanks again
    – js_248
    Commented May 26, 2018 at 15:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.