3

each of "CompletableFuture.runAsync" mentioned in the code below does some calculations, an i want to get the results each time i call "CompletableFuture.runAsync". or in other words, i want each of "future0,future1,future2,future3" to contain the result of each call to "CompletableFuture.runAsync" respectively

how can i do that.

*Update:

my requirements are, for each call to CompletableFuture.runAsync i do some calculations and an ArrayList of these values should be returned. and after the four calles to the CompletableFuture.runAsync , i want to some further calculations on the ArrayLists returned.

code:

    if (this.laplaceImgList != null) {
                        if (!this.laplaceImgList.isEmpty()) {
                            if (this.laplaceImgList.size() == 3) {
                                //executor
                                ExecutorService orintMapExe;
                                CompletableFuture<Void> future0 = null;
                                CompletableFuture<Void> future1 = null;
                                CompletableFuture<Void> future2 = null;
                                CompletableFuture<Void> future3 = null;

                                orintMapExe = Executors.newFixedThreadPool(1);
                                future0 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_ZERO , this.laplaceImgList), orintMapExe);
                                future1 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_45 , this.laplaceImgList), orintMapExe);
                                future2 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_90 , this.laplaceImgList), orintMapExe);
                                future2 = CompletableFuture.runAsync(new orintMapRun(SysConsts.ORINT_DEG_135 , this.laplaceImgList), orintMapExe);
                                CompletableFuture.allOf(future0,future1,future2,future3).join();//blocks the main thread till future0, and future1 finishes
Amrmsmb
  • 1
  • 27
  • 104
  • 226
  • What is `orintMapRun` doing? Please paste the code. – akhil_mittal May 08 '15 at 14:46
  • @akhil_mittal it is the runnable class – Amrmsmb May 08 '15 at 14:47
  • If you want to return some result you should have used `Callable`. Why do you need `CompletableFuture`? This can be done by submitting the tasks to executor service. – akhil_mittal May 08 '15 at 14:53
  • @akhil_mittal so, is all what i need is to change the runnable to callable? – Amrmsmb May 08 '15 at 14:53
  • We generally use `futures` to represent some code running by other thread. But if you want to create a `Future` representing some event that you know will occur but you don't have any asynchronous job underlying this future then you use `CompletableFuture` which will complete on that event. – akhil_mittal May 08 '15 at 14:56
  • What exactly is your requirement? – akhil_mittal May 08 '15 at 14:57
  • This can be done using `future` as well. Why do you want to use `CompletableFuture`? – akhil_mittal May 08 '15 at 15:03
  • @akhil_mittal would you please provide an example how to do that with future, i am new to this Future and compatable future – Amrmsmb May 08 '15 at 15:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77325/discussion-between-akhil-mittal-and-user2121). – akhil_mittal May 08 '15 at 15:11

2 Answers2

5

Here I am posting an example where your job will return a Future and you get a list of values you supply. As you expect a result (List actually) it implements Callable.

public class OrintMapRun implements Callable<List<Integer>> {
    final int partOne, partTwo;
    final List<Integer> resultList = new ArrayList<>();
    public OrintMapRun(int partOne, int partTwo) {
        this.partOne = partOne;
        this.partTwo = partTwo;
    }

    @Override
    public List<Integer> call() throws Exception {
        resultList.add(partOne);
        resultList.add(partTwo);
        Thread.sleep(5000); //simulate some computation
        return resultList;
    }
}

Now you need to submit those Callables to executor service as shown:

public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService orintMapExe = Executors.newFixedThreadPool(4);
        List<Future<List<Integer>>> futures = new ArrayList<>();

        futures.add(orintMapExe.submit(new OrintMapRun(10, 10)));
        futures.add(orintMapExe.submit(new OrintMapRun(20, 20)));
        futures.add(orintMapExe.submit(new OrintMapRun(30, 30)));
        futures.add(orintMapExe.submit(new OrintMapRun(40, 40)));

        orintMapExe.shutdown();
        try {
            orintMapExe.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        for(Future<List<Integer>> future : futures) {
            List<Integer> result = future.get();
            System.out.println(result);
        }
    }

Once you get the result of all futures it will be:

[10, 10] [20, 20] [30, 30] [40, 40]

On a side note class name should always start with capital letter.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
0

In addition to the answer from @i_am_zero, you can also use CompletionService, which is a wrapper of the simple ExecutorService. The benefit of CompletionService is that you can always get the earliest finished Future<> object and the afterward operation won't be blocked by the last finished task. Based on @i_am_zero's answer, a simple improvement is like the following:

public static void main(String[] args) throws ExecutionException, InterruptedException {
    ExecutorService orintMapExe = Executors.newFixedThreadPool(4);
    CompletionService service = new ExecutorCompletionService(orintMapExe);
    List<Future<List<Integer>>> futures = new ArrayList<>();

    futures.add(orintMapExe.submit(new OrintMapRun(10, 10)));
    futures.add(orintMapExe.submit(new OrintMapRun(20, 20)));
    futures.add(orintMapExe.submit(new OrintMapRun(30, 30)));
    futures.add(orintMapExe.submit(new OrintMapRun(40, 40)));

    for(int i=0; I< futures.size();i++) {
        List<Integer> result = service.take().get();
        System.out.println(result);
    }
}

In most cases, CompletionService should be preferred than the barebone ExecutorService unless you don't care the performance. There're some good articles explaining the benefits such as https://dzone.com/articles/executorservice-vs.

CompletionService is good enough for your question, but if you have interest, for CompletableFuture, I wrote up a simple blog on one scenario which is a great fit for using it: https://medium.com/@zhongzhongzhong/beauty-of-completablefuture-and-where-should-you-use-it-6ac65b7bfbe

Zhong Hu
  • 272
  • 2
  • 5