0

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 immediately `invokeAll` returns. As long as you call `get` on the `Future`s, that will wait until the result is available. Please explain exactly what the problem is. Add ing the code of `createCSV` would help. – tgdavies Aug 08 '23 at 00:37
  • 2
    [`invokeAll`](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/ExecutorService.html#invokeAll(java.util.Collection)) is defined to return only once every task has completed (normally or exceptionally). And you have to call [`get`](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/Future.html#get()) 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 [mre]. – Slaw Aug 08 '23 at 01:05
  • 1
    What behaviour leads you to conclude that `calculateRows` *hasn't* finished running? – tgdavies Aug 08 '23 at 03:00
  • I receive the following error java.util.concurrent.ExecutionException: java.util.NoSuchElementException a number of times equal to the number of times that my calculateRows did not run. I placed a println at the begining of calculateRows and counted the missing runs. – PondleDondle Aug 08 '23 at 03:18
  • Then your problem isn't that the code continues without waiting for the tasks to complete. An `ExecutionException` means the task completed, but exceptionally. The underlying error is a `NoSuchElementException`; 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?](https://stackoverflow.com/q/3988788/6395627). And if you need more help, please provide a [mre]. – Slaw Aug 09 '23 at 00:44

0 Answers0