I have a method that is called with multi threading and runs to around 99% completion. At this point it runs the next method which needs the first method to of finished running before attempting as it takes data created from that and places it into a file.
public static void main(String[] args)
{
final int MAX_THREADS = 2;
ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
List<String> row = new ArrayList<>();
for (int a : listA)
{
for (double b : listB)
{
for (int c : listC)
{
for (int d : listD)
{
for (int e : listE)
{
for (int f : listF)
{
for (double g : listG)
{
for (double h : listH)
{
for (double i : listI)
{
if (i < h)
{
try
{
Callable<RowEarnings> task = () -> calculateRows("C://CSV", a, b, c, d, e, f, g, h, i);
tasks.add(task);
}
catch (Exception e)
{
System.out.println("Error Message");
e.printStackTrace();
}
}
}
}
}
}
}
}
}
try {
List<Future<RowEarnings>> results = executor.invokeAll(tasks);
createCSV(directory, results, a, b);
}
catch (InterruptedException e)
{
System.out.println("Error while invoking tasks.");
e.printStackTrace();
}
}
}
executor.shutdown();
try
{
while (!executor.isTerminated())
{
}
System.out.println("TEST COMPLETE");
}
catch (Exception e)
{
System.out.println("Thread execution interrupted.");
Thread.currentThread().interrupt();
}
}
How can I stop it running createCSV until all the calculateRows has finished running for that for loop? It seems to be that calculateRows is taking too long and it just tries to run createCSV as it thinks its finished.
Edit:
Adding createCSV code:
public static void createCSV(String directory, List<Future<RowEarnings>> futures, int a, double b)
{
List<RowEarnings> rowComplete = new ArrayList<>();
for (Future<RowEarnings> future : futures)
{
try
{
RowEarnings rowEarnings = future.get();
if (rowEarnings != null)
{
rowComplete.add(rowEarnings);
}
}
catch (Exception e)
{
System.out.println("Error retrieving task result.");
e.printStackTrace();
Throwable cause = e.getCause();
if (cause != null)
{
System.out.println("Cause of the exception:");
cause.printStackTrace();
}
}
}
StringBuilder outputCSVFilePath = new StringBuilder(directory);
outputCSVFilePath.append(Main.resultFolder).append(a).append("_").append(b).append(".csv");
System.out.println(outputCSVFilePath);
try
{
CSVEditor.createCSVFile(outputCSVFilePath.toString(), rowComplete, RowEarnings::mapToStringArray);
System.out.println("Complete");
}
catch(IOException e)
{
System.out.println("BROKE AINT IT");
}
}
Essentially calculateRows should run a few thousand times for each running of createCSV, each time calculateRows runs it sends out a row of the csv and so forth. Sometimes there can be a couple million rows being sent to each createCSV.
createCSV
will be called immediatelyinvokeAll
returns. As long as you callget
on theFuture
s, that will wait until the result is available. Please explain exactly what the problem is. Add ing the code ofcreateCSV
would help.invokeAll
is defined to return only once every task has completed (normally or exceptionally). And you have to callget
on each future anyway to get the result (or error), which is also defined to wait until the task is complete. I would guess you have improperly synchronized code in the tasks themselves. Please provide a minimal reproducible example.calculateRows
hasn't finished running?ExecutionException
means the task completed, but exceptionally. The underlying error is aNoSuchElementException
; you should look at whatever line of code in the task that is throwing that error and figure out why. If you don't know how to determine which line is throwing that error, then I suggest reading What is a stack trace, and how can I use it to debug my application errors?. And if you need more help, please provide a minimal reproducible example.