Amandeep Singh
Amandeep Singh

Reputation: 307

How to wait for threads to complete in Java where threads are initiated using run()

I am starting these threads:

          ThreadingHDFSUsage HDFSUsage=new ThreadingHDFSUsage(dcaps);  
          ThreadingRAMandContainers RAMandContainers=new ThreadingRAMandContainers(dcaps);  
          ThreadingCoreNodesHDFSUsage CoreNodesHDFSUsage=new ThreadingCoreNodesHDFSUsage(dcaps);
          ThreadingApplicationMonitoring ApplicationMonitoring= new ThreadingApplicationMonitoring(dcaps);

How should i wait for all these threads to complete before doing some other operation.

My sample thread class code for one thread operation is:

public class ThreadingHDFSUsage extends Thread {

//private PhantomJSDriver driver;

private DesiredCapabilities dcaps;

 public ThreadingHDFSUsage(DesiredCapabilities dcaps) {
    // TODO Auto-generated constructor stub
     this.dcaps = dcaps;
}

public void run(){  
     System.out.println("task HDFS Usage");  

    PhantomJSDriver driver = new PhantomJSDriver(dcaps);
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
     System.out.println(".........HDFS Usage..........");
     String OverallHDFSUsage[] = null;
    try {
        OverallHDFSUsage = HDFSUsage.getWebData(driver,"http://1.2.3.4:8888/dfshealth.html#tab-overview","//*[@id=\"tab-overview\"]/table[2]/tbody/tr[2]/td","");
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     String OverallHDFSUsage1 = OverallHDFSUsage[0];


 }  
}

Similarly, I have relevant code for other threads.

So, how do i wait for all these 4 thread operation to complete?

Upvotes: 2

Views: 204

Answers (3)

CodeBlind
CodeBlind

Reputation: 4569

Both of the other answers are correct, but for completeness, there's yet another way to do what you want using a Semaphore. This method won't yield results different from any of the other answers, but may be faster if any of your threads have to do something expensive after the results you want are obtained, prior to returning. Inside each of your threads, call s.release() as soon as all pertinent work is finished. Your controller thread might look like this ...

Semaphore s = new Semaphore(0);
//start all four of your threads here and pass 's' to each
s.acquire(4);

... and your worker threads might look like this:

@Override
public void run(){
    //compute results
    s.release(1);
    //do expensive cleanup and return
}

Upvotes: 0

Victor Sorokin
Victor Sorokin

Reputation: 11996

There's also CompletionService in JDK concurrent package. To use it, you switch from explicit Threads to tasks, represented as instances of Callable<ResultType> or Runnable. While code may look slightly more complicated, it is quite convenient, once you became used to it:

import java.util.concurrent.*;

class Test {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        CompletionService<String> completionService = new ExecutorCompletionService<>(Executors.newCachedThreadPool());
        completionService.submit(() -> {
            Thread.sleep(5000);
            return "sleeped for 5000 millis";
        });
        completionService.submit(() -> {
            Thread.sleep(1000);
            return "sleeped for 1000 millis";
        });
        // etc
        System.out.println("Completed: " + completionService.take().get());
        System.out.println("Completed: " + completionService.take().get());
    }

}

Upvotes: 0

Nitek
Nitek

Reputation: 2614

Just join() them again:

HDFSUsage.join();  
RAMandContainers.join();
CoreNodesHDFSUsage.join();
ApplicationMonitoring.join();

Each join() waits for the specific thread to finish.

Upvotes: 2

Related Questions