For performance reason I would like to use a forEach loop of a parallel Lambda stream in order to process an instance of a Collection
in Java. As this runs in a background Service
I would like to use the updateProgress(double,double)
method in order to inform the user about the current progress.
In order to indicate the current progress I need a certain progress indicator in form of a Integer
counter. However, this is not possible as I can only access final
variables within the Lambda expression.
Code example see below, Collection
is only a place holder for any possible instance of a Collection
:
int progress = 0;
Collection.parallelStream().forEach(signer -> {
progress++;
updateProgress(progress, Collection.size());
});
I'm aware that I can solve this problem by using a simple for-loop. However, for performance reason it would nice to solve it in this way.
Does anybody know a more or less neat solution to this?
As proposed by markspace, using an AtomicInteger is a good solution:
I would not use the runLater() variant as your goal is a high performance, and if many parallel threads will generte JavaFX 'runLater' tasks, you will again create a bottleneck...
For the same reason I would NOT call an update to the ProgressBar each time, but use a seaparte JavaFX Timeline to update the progress bar in regular intervals independently from the processing threads.
Here is a full code comparing sequential and parallel processing with ProgressBar. If you remove the sleep(1) and set the number of items to 10 million it will still work concurrently and efficiently...
The naive solution would be to have progress as a field of some surrounding object; then referring to
progress
from a lambda closure would actually meanthis.progress
, wherethis
isfinal
, thus the compiler would not complain. However, the resulting code would access theprogress
field from multiple threads concurrently, which could cause race conditions. I suggest restricting access to theprogress
field to the JavaFX application thread, by usingPlatform.runLater
. The whole solution then looks like this: