Основной поток ожидания двух параллельных потоков детей java - PullRequest
1 голос
/ 31 октября 2019

первое, что я пытаюсь сделать:

Во время выполнения основного потока я хочу приостановить основной поток и запустить два параллельных потока. Как только оба параллельных потока завершатся, я бы хотел начать снова с основного потока.

Что я пробовал:

    ...
    ...
    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)
...

Пользовательский класс построителя потоков

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
    }

Не ясно, что здесь происходит, но оно определенно не работает. Как только я вызываю join, все останавливается и основной поток никогда не перезапускается. (Я ставлю точку останова после объединений, чтобы увидеть, когда основной поток перезапускается).

Возможно, есть некоторая путаница с этими понятиями, и я также не уверен, нужно ли мне использовать как барьер, так иприсоединяется или просто один из тех методов.

Спасибо

Davide

Ответы [ 2 ]

1 голос
/ 31 октября 2019

Как уже упоминалось в комментариях, я бы также предложил использовать CompletableFuture. Очень простой пример ваших описанных требований может выглядеть следующим образом:

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

Возможно, вы захотите добавить дополнительную / некоторую обработку исключений в этот пример. Но это должно дать представление о том, как это может работать.

1 голос
/ 31 октября 2019

Возможно, вы решите использовать Java CompletableFuture для достижения цели.

Используя его функции, такие как supplyAsync или runAsync , вы можете завести ребенкатемы и присоединить их соответствующий результат в конце. Или вы можете просто позволить основному потоку дождаться завершения следующих потоков.

Недавно мне удалось реализовать пример функции рассеяния-сбора с использованием того же класса.

Проверьте Java Doc на наличие дополнительных предложений и найдите лучшую доступную функцию: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html

...