3

I am currently evaluating various concurrency solutions to solve a business problem. The use case is akin to the "embarassingly-parallel" algorithim.

Basically for a single user request, we need to retrieve data from multiple different data sources before computing the response. Currently all 3 DAO calls are made serially but have no inter dependencies so can be made in parallel.

Solutions implemented so far:

  • java.util.concurrent.ExecutorService using Callables and Futures
  • org.springframework.scheduling.annotation.Async to enable spring manage the thread pool but sill allow me to make aysnchronous calls
  • Akka (deemed overkill) for our relatively simple use case

Last framework I wanted to evaluate was Java ForkJoin framework, I can see multiple examples of use of RecursiveTasks, but my use case is not recursive in nature so doesnt fit the model: if task is small enough do it else split it and recursively call same method (i.e. divide and conquer)

My use case is, split task into 3 tasks. fork all 3 and join again. Is this even a valid use case for the ForkJoin implementation? Or should i stick with the generic ExecutorService implementation.

  • Have you checked the [`ExecutorCompletionService` class](http://docs.oracle.com/javase/7/docs/api/index.html?java/util/concurrent/ExecutorService.html)? You can run your 3 calls in parallel and receive the results as and when they become available. – assylias Jul 04 '12 at 09:46
  • Related: http://stackoverflow.com/questions/7926864/how-is-the-fork-join-framework-better-than-a-thread-pool – assylias Jul 04 '12 at 12:51

4 Answers4

0

As you already mentioned, there isn't any recursion involved in your use case. If you just need to run 3 tasks in parallel and wait for them to complete, ExecutorService.invokeAll seems like the simplest solution.

casablanca
  • 69,683
  • 7
  • 133
  • 150
0

For only 3 parallel tasks, the simplest method is to run 3 threads, and wait them to finish with thread.join().

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
  • I personally think that there is little value in using the low level API unless you really need a low level control, which is not the case here. Executors make the code shorter (slightly) and less error prone. – assylias Jul 04 '12 at 10:05
  • Creating and destroying threads is quite an intensive operation for the OS. If you use a ThreadPoolExecutor, it will recycle the threads for consecutive user calls. – GeertPt Jul 04 '12 at 10:25
  • @greyfairer: recycling makes sense if there are many client requests. Probably this is so but topic starter did not stress it. – Alexei Kaigorodov Jul 05 '12 at 07:39
0

The advantage of an ExecutorService is that it can keep thread pool. So in your case, for multiple consecutive calls, the threads will be reused, which saves the OS some cycles to stop and create new threads.

The further advantage of the ForkJoinPool, is that it can 'steal' work. AFAIK, what it means is that it allows one thread that has finished a task to immediately execute another task with much less overhead than the ExecutorService.

In your case, the advantage of the ForkJoinPool seems minimal.

GeertPt
  • 16,398
  • 2
  • 37
  • 61
0

Definitelly not ForkJoinPool.

It's stated in javadoc that you have to avoid pushing any tasks that could cause any IO, except in some cases output to async streams.

Tasks should also not perform blocking IO... 100 to 10000 basic computational steps.

So it should probably better to use either container concurrency management or ExecutorServices with Futures.

zubrabubra
  • 504
  • 3
  • 8