I have an abstract class extending SwingWorker
called FetchWorker
to do some background data fetching and modifying the data that is fetched for my application. In my FetchWorker
is an inner class of StatisticLayerController
. This StatisticLayerController is extended by two classes. I initialize new threads within my FetchWorker
to do some calculations. I used to use the ExecutorService of TrackHistoryLayerController.
Like below:
public class TrackHistoryLayerController extends StatisticLayerController
{
private final ExecutorService heatMapAdderExecutor;
...
public AdsbFetchWorker(...) extends FetchWorker
{
super(...);
}
@Override
protected final List<ADSBTrack> doInBackground() throws Exception
{
filtered.forEach( track -> {
this.heatMapAdderExecutor.submit( new HeatmapAdderHelper( ... ) );
} );
while ( this.latch.getCount() != 0 )
{
this.publishValue( ( int ) this.latch.getCount() );
}
this.latch.await();
this.publishValue( ( int ) this.latch.getCount() );
if ( this.createImage() )
{
this.placeImage();
}
return filtered;
}
}
So in this case HeatMapAdderHelper
is my Helper thread which does some calculation for me. It was all working and all was fine.
But now I wanted to change class structure a bit more, I wanted to make my Controller
class abstract
and I no longer wanted my Worker
classes to be an inner class.
My question is, I cannot(should not) create ExecutorService
within a Worker
since the worker is going to be initialized each time event is invoked. Only thing I could do would be passing the ExecutorService from the Controller
as an argument to the SwingWorker
but would that be a good practice? Thank you in advance.
You can of course also just use the default ExecutorService
provided by CompletableFuture
by doing
filtered.forEach( track -> {
CompletableFuture.runAsync(new HeatmapAdderHelper( ... ) );
} );
As a side note, this
while ( this.latch.getCount() != 0 )
{
this.publishValue( ( int ) this.latch.getCount() );
}
this.latch.await();
this.publishValue( ( int ) this.latch.getCount() );
looks very dodgy... a busy loop while waiting for the results? Also, why do you await
the latch after you already waited in the loop? Assuming the latch is a CountDownLatch
.
I'm sure if you provided even more context, we could give a better overall solution.
It looks like you can just do something like
CompletableFuture<Void>[] futures =
filtered.stream().map(t -> new HeatmapAdderHelper(t))
.map(CompletableFuture::runAsync)
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).andThen(createImage());
Or with a CountDownLatch
:
CountDownLatch latch = new CountDownLatch(filtered.size());
filtered.forEach(f -> {
CompletableFuture.runAsync(new HeatmapAdderHelper(f))
.thenRun(latch::countDown);
});
latch.await();
createImage();