I have something like this:
// sequential version
for(var t: tasks){
// run() is a time consuming method (approx. 20-30 seconds)
t.run();
}
I have approx. 1000 (independent) tasks and the above needs approx. 1000 x 25 seconds. The run()-method is only CPU intensive (there are no I/O Operations involved).
I switched to parallelStream:
// parallel version
tasks.parallelStream().forEach(Task:run);
and measured that with parallelStream each task.run() needs approx. 15-20 seconds. So it's definitely a little faster than using the sequential version.
Can I use parallelStream (with its fork-join) for such long running operations (each task.run() needs approx. 15-20 seconds) or would it be better to use executorServices with custom thread pools (for example, because of system stability, performance, etc.)?
What I want to know if there is any harm when using parallelStream (fork-join) for such long running tasks. I have thought that fork-join should only be used for very short running tasks (max. 1-2 seconds), but I am not sure if so and why.
Collection#parallelStream is simpler - you need less code, but you have no control over when, or even if, parallelism is used.
ExecutorService gives you a lot of control over parallel processing, but exposes more of the workings, so you need more code and more knowledge (but not a lot of either).
Try parallel stream first. If that seems good enough and you’re not processing many other requests, stop there.
If parallelism seems not be to sufficient, or if you are processing other requests, use executor service, because all streams share a single thread pool, so if they are kept busy, other stream based code will freeze.