1
votes

I am looking for a design pattern where the parent thread will spawn multiple child threads. Each child thread will perform some computation and return an appropriate result.

The parent thread will be waiting for the child threads to complete. After all child threads are completed, the consolidated result will be sent to the parent thread.

The parent thread will then proceed with consolidated result.

3
Why are you not using future? cyclic barrier is intended for use as repeatable waiting of one or more threads. For wait one-short thread(s) join is sufficient. - Tsyvarev
Sounds like ForkJoinTask or, if you insist on doing it manually, a Phaser will work. - Ben Manes
Focused the title and question to help clarify the problem, dropped an inappropriate tag and improved the grammar. - Brett Walker
Will the parent thread be consolidating the results, or is there some other process that is doing this piece of work? - Brett Walker
Hi Brett Walker yes parent thread will be consolidating results and perform some actions on basis of result obtained from child threads - Timothy Drisdelle

3 Answers

0
votes

Check the join method of Thread class. Here is a working sample:

import java.lang.*;

public class Threads {

 public void callChildren() throws Exception {

   Thread t = new Thread(new ChildThread());
   t.start();
   t.join();
   System.out.print(t.getName());
   System.out.println(", status = " + t.isAlive());
  }

   public static void main(String[] args) throws Exception{

        for(int i = 0 ; i < 4; i ++) {
            new Threads().callChildren();
         }

         System.out.println("Printing from Parent thread after all child thread are complete.");
   }


  private class ChildThread implements Runnable{

    @Override
    public void run() {
        System.out.println("Thread started:::"+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread ended:::"+Thread.currentThread().getName());
    }
   }

} 
0
votes

Some existing answers recommend spawning threads manually -- I would not do that, but rather use an ExecutorService instead.

If you are allowed to use a 3rd party library, Guava will do the trick: Submitting your child tasks to a ListeningExecutorService will give you back a ListenableFuture<T> (with T being your result type). You can then e.g. use Futures.allAsList to combine all child task futures into one future (encapsulating the list of result values). If you then wait on this one future (with get), you effectively wait on all child tasks. Once it completes, you can consolidate all result values and continue with your parent logic.

Here's a very minimal example:

public class Example {

    private static final int NUMBER_OF_CHILD_TASKS = 5;

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);

        List<ListenableFuture<String>> childTaskFutures = IntStream.range(0, NUMBER_OF_CHILD_TASKS).mapToObj(
                taskIndex -> listeningExecutorService.submit(new ChildTask(taskIndex))
        ).collect(Collectors.toList());

        ListenableFuture<List<String>> parentFuture = Futures.allAsList(childTaskFutures);
        try {
            List<String> results = parentFuture.get();
            results.forEach(System.out::println);
        } catch (Exception e) {
            // proper handling...
        }
    }

    private static final class ChildTask implements Callable<String> {

        private final String taskName;

        private ChildTask(int taskIndex) {
            this.taskName = "Task " + taskIndex;
        }

        @Override
        public String call() throws Exception {
            System.out.println(taskName + " executing...");
            Thread.sleep(1000);
            return "Result of " + taskName;
        }
    }

}

If you can't use a 3rd party library, you can use a "traditional" ExecutorService to spawn the child tasks and use an ExecutorCompletionService to process the resulting futures. The linked javadocs give examples for both aspects of the problem.

-1
votes

Threads cannot return a result. Child threads can communicate with the creating thread when the creator passes a reference to itself ("this") to the created threads, such as:

MyThread thd1 = new MyThread(this, latch);

The latch is a reference to a CountDownLatch. The creator also has a method that the created thread will call when it completes, such as:

public void saveResult1 (Object something) {

  object1 = something;
  latch.countDown();

}

The creator simply waits for all threads to finish with an await.

try {
    latch.await();
  } catch (InterruptedException ignore) {}

When each created thread finishes its work it can call method saveResult... on the creator thread that saves the result somewhere and does a count down.