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.

5
  • createCSV will be called immediately invokeAll returns. As long as you call get on the Futures, that will wait until the result is available. Please explain exactly what the problem is. Add ing the code of createCSV would help.
    – tgdavies
    Commented Aug 8, 2023 at 0:37
  • 2
    invokeAll is defined to return only once every task has completed (normally or exceptionally). And you have to call 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 minimal reproducible example.
    – Slaw
    Commented Aug 8, 2023 at 1:05
  • 1
    What behaviour leads you to conclude that calculateRows hasn't finished running?
    – tgdavies
    Commented Aug 8, 2023 at 3: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. Commented Aug 8, 2023 at 3: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?. And if you need more help, please provide a minimal reproducible example.
    – Slaw
    Commented Aug 9, 2023 at 0:44

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.