简体   繁体   中英

Main thread to wait two parallel threads children java

first what i am trying to do:

During the main thread execution i want to pause the main thread and start two parallel threads. As soon as both this parallel threads terminate, i'd like to start again with the main thread.

What i tried:

    ...
    ...
    main thread is executing
    ...
    ...
CyclicBarrier barrier = new CyclicBarrier(2);
Thread child1 = new Thread(new ThreadBuilderTask(barrier,0));
Thread child2 = new Thread(new ThreadBuilderTask(barrier,1));

child1.start();
child2.start(); 

/* Now i'm expecting that child1 and child2 are running in parallel calling their fooFunction */

child1.join();
child2.join(); 
/*Now i'm expecting that main thread will wait for child1and also for child2 (that are running in parallel).*/

... main thread starts again after both child1 and child2 finished (reached the await of the barrier) 
... (break point set here, never reached)
...

Thread builder custom class

public class ThreadBuilderTask implements Runnable{
    private CyclicBarrier barrier;
    private int index;
    ...setters and getters..

    @Override
    public void run() {
        fooFunction(this.getIndex());
        try {
            this.getBarrier().await();
        } catch (InterruptedException | BrokenBarrierException e) {
            return;
        }
    }

    public ThreadBuilderTask(CyclicBarrier barrier,int index){
      this.barrier = barrier;
      this.index = index;
    }

    public fooFunction(int index){
        //Something taking some seconds to execute
    }

It's not clear what is happening here but it is definetely not working. As soon as i call join everything stops and the main thread never restart. (I put a breakpoint after the joins to see when the main thread restarts).

Maybe there is a bit of confusion with these concepts and also i'm not sure if i need to use both the barrier and the joins or simply one of those techniques.

Thanks

Davide

You may consider to use Java CompletableFuture to achieve the objective.

Using its functions like supplyAsync or runAsync you may start child threads and join their respective result in the end. Or you can simply let the main thread wait until the subsequent threads completes.

Recently I managed to implement a sample scatter-gather function using the same class.

Check Java Doc for more offerings and to find best available function: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html

As mentioned in the comments I'd also suggest to use CompletableFuture . A very basic example of your described requirements could look like this:

final Runnable runnable1 = ...;
final Runnable runnable2 = ...;

CompletableFuture<Void> future1 = CompletableFuture.runAsync(runnable1);
CompletableFuture<Void> future2 = CompletableFuture.runAsync(runnable2);

CompletableFuture.allOf(future1, future2).get(); // waits for both runnables to finish

You might want to add more/some exception handling to this example. But it should give an idea how this might work.

First of all, it's worth analyzing why your program does not give you the desired output. The main thread creates 2 child threads and completes. If you want to wait till two child threads are completed, then you have to call barrier.await(); in your main thread after starting the two child threads. This will keep your main thread blocking until two child threads complete.

child1.start();
child2.start();

barrier.await();

Nonetheless, CountDownLatch is a much better candidate for your usecase. Just pass a latch to each child thread which does the computation and upon successful completion counts down the latch. The main thread creates two threads, starts them and call await() on the latch, which blocks the main thread until two child threads completed. Once the latch reaches it's terminal state the await method returns and the main thread continues it's execution. Here's how it looks.

public class ThreadBuilderTask implements Runnable {
    private CountDownLatch latch;
    private int index;

    public ThreadBuilderTask(CountDownLatch latch, int index) {
        this.latch = latch;
        this.index = index;
    }

    @Override
    public void run() {
        fooFunction(index);
        latch.countDown();

    }

    public void fooFunction(int index) {
        // Something taking some seconds to execute

    }
}


final CountDownLatch completionLatch = new CountDownLatch(2);
Thread child1 = new Thread(new ThreadBuilderTask(continuationLatch, 0));
Thread child2 = new Thread(new ThreadBuilderTask(continuationLatch, 1));

child1.start();
child2.start();

completionLatch.await();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM