So I have an ExecutorService successfully blocking and running linearly right now. My trouble is, I am trying to add a status update and I can't figure out how to get Futures to settle one-item at a time. It seems that by the time the first item in my Future<> is ready so is the last. I'm hoping to find a place where I can know how many tasks my executorService has remaining/total so I can calculate a simple percentage indicator. Please note I intend on recycling my Executor and don't want to shut it down.
ExecutorService updateService = Executors.newSingleThreadExecutor();
Callable<String> callHour = () -> {
//doStuff, unaware of total number of hourCalls
return "done";
};
private void startMe(int hours){
List<Future<String>> futureHours;
List<Callable<String>> hourCalls = new ArrayList<>(hours);
for (int hour = 0; hour < hours; ++hour) {
hourCalls.add(callHour); //queue list (not running yet)
}
try {
//executes queue and blocks thread
futureHours = updateService.invokeAll(hourCalls);
futureHours.get(0).get();//performs blocking
} catch (Exception e) {
e.printStackTrace();
}
}
}
There are two things at work here.
Firstly, if we take a look at the documentation of ExecutorService#invokeAll(...)
, we see that it returns
[...] a list of Futures holding their status and results when all complete. [...]
(emphasis added by me)
You most probably want to use Executor#submit(...) instead.
Secondly, you have no guarantee that the task coupled to futureHours.get(0)
is executed first. I would suggest using Future#isDone()
with some additional logic:
private void startMe(int hours) {
[...]
try {
[...]
ArrayList<Future<String>> futureHoursDone = new ArrayList<>();
final int numTasks = futureHours.size();
int done = 0;
double percentageDone = 0.0d;
while (futureHours.isEmpty() == false) {
for (int index = 0; index < futureHours.size(); ++index) {
Future<String> futureHour = futureHours.get(index);
if (futureHour.isDone()) {
futureHours.remove(index);
futureHoursDone.add(futureHour);
--index;
++done;
percentageDone = done / (double) numTasks;
}
}
}
} catch (Exception e) {
// TODO: don't forget to HCF (https://en.wikipedia.org/wiki/Halt_and_Catch_Fire) :)
e.printStackTrace();
}
}
(This is a rough sketch. To make the progress, i.e. percentage
, visible to the outside, you would have to make it an attribute and accessible through, e.g., some getter)