Search code examples
javamultithreadingwaitnotify

How to make thread wait if prerequisite was not yet done processing and resumes once prerequisite is finished?


I am new to Java multithreading. I wanted to perform a process executor program. Each process contains zero to many prerequisites (List of String of a Process)

My goal is to run process one by one. And in case the current thread prerequisites are not yet finished, it will wait and resume once all of its prerequisite process are done executing.

I'm not sure if this is possible. Hope you can help me. Please help me make it more simple and easy to understand.

My current program output is: Thread starts Back Up Thread starts Transfer Report Thread starts Archive Report Thread works Back Up Thread waits Transfer Report Thread waits Archive Report Thread finished Back Up Adding Back Up to finished process.

My expected output: Thread starts Back Up Thread starts Transfer Report Thread starts Archive Report Thread works Back Up Thread waits Transfer Report Thread waits Archive Report Thread finished Back Up Adding Back Up to finished process. Thread works Transfer Report Thread finished Transfer Report Adding Transfer Report to finished process. Thread works Archive Report Thread finished Archive Report Adding Archive Report to finished process. == End ==

Below are my current codes:

Main Application

public class ThreadApp {

    public static void main(String[] args) {
        List<EODProcess> eodProcesses = new ArrayList<>();
        eodProcesses.add(new EODProcess("Back Up", new ArrayList<String>()));
        eodProcesses.add(new EODProcess("Archive Report", Arrays.asList("Transfer Report")));
        eodProcesses.add(new EODProcess("Transfer Report", Arrays.asList("Back Up")));
        
        int count = eodProcesses.size();
        CountDownLatch latch = new CountDownLatch(count);
        CyclicBarrier barrier = new CyclicBarrier(count);
        ExecutorService pool = Executors.newFixedThreadPool(count);

        List<String> finishedProcess = new ArrayList<>();
        
        for (EODProcess eodProcess : eodProcesses) {
            pool.execute(() -> {
                try {
                    System.out.println("Thread starts " + eodProcess.getProcess());
                    Thread.sleep(1000);
                    
                    // Wait IF
                    // Process Prerequisite is not empty
                    // Process Prerequisite is not yet finished
                    while(!eodProcess.getPrerequisites().isEmpty() ||
                            !finishedProcess.containsAll(eodProcess.getPrerequisites())) {
                        System.out.println("Thread waits " + eodProcess.getProcess());
                        barrier.await();
                    }
                    
                    System.out.println("Thread works " + eodProcess.getProcess());
                    Thread.sleep(1000);
                    System.out.println("Thread finished " + eodProcess.getProcess());
                
                    System.out.println("Adding " + eodProcess.getProcess() + " to finished process.");
                    finishedProcess.add(eodProcess.getProcess());
                    
                } catch (Exception e) {
                    System.err.println("Worker thread inrerrupted " + eodProcess.getProcess());
                } finally {
                    latch.countDown();
                }
            });
        }

        try {
            // wait for the threads to be done
            latch.await();
            System.out.println("== End == ");
        } catch (InterruptedException e) {
            System.err.println("Starting interrupted");
        }
        pool.shutdown();
    }

}

EODProcess Object

public class EODProcess {

    private String process;
    
    private List<String> prerequisites = new ArrayList<>();
    
    public EODProcess(String process, List<String> prerequisites) {
        this.process = process;
        this.prerequisites.addAll(prerequisites);
    }

    public String getProcess() {
        return process;
    }

    public void setProcess(String process) {
        this.process = process;
    }

    public List<String> getPrerequisites() {
        return prerequisites;
    }

    public void setPrerequisites(List<String> prerequisites) {
        this.prerequisites = prerequisites;
    }

}

Solution

  • I made my implementation simpler. In my callable object, I do these.

    @Override
    public String call() throws Exception {
        while (!ThreadApp.finishedProcess.containsAll(eodProcess.getPrerequisites())) {
            System.out.println(eodProcess.getProcess() + " still waiting for prerequisites...");
            Thread.sleep(3000);
        }
        System.out.println(eodProcess.getProcess() + " working...");
        System.out.println(eodProcess.getProcess() + " done!");
        ThreadApp.finishedProcess.add(eodProcess.getProcess());
        return eodProcess.getProcess();
    }
    

    Thank you all for your help!