2017-02-16 18 views
0

Редактировать: У меня вопрос другой, он не имеет отношения к связанному вопросу.Java Ожидание завершения всех тем

У меня есть следующий код с обработчиком завершения.

FutureTask<Void> futureTask = new FutureTask<Void>(() -> { 
    System.out.println("callback"); 
    return null; 
}); 

Runnable task =() -> { 
    for(int i=0; i<5; i++) { 
     System.out.println(Thread.currentThread().getName() + " " + i); 
    } 
    futureTask.run(); 
}; 

new Thread(task).start(); 
new Thread(task).start(); 

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

Я вдохновлен этим answer, но кажется, что это часть какой-то библиотеки, в то время как я ищу собственное решение.

Completable Future ???

Вот моя попытка с завершающимися фьючерсами с обработчиком результата в конце.

public void test() { 
    CompletableFuture 
      .supplyAsync(() -> method1()) 
      .supplyAsync(() -> method2()) 
      .supplyAsync(() -> result()); 
} 

public String method1() { 
    System.out.println("calling 1"); 
    return "method1"; 
} 

public String method2() { 
    System.out.println("calling 2"); 
    return "method2"; 
} 

public String result() { 
    System.out.println("result"); 
    return "result"; 
} 
+0

Почему «futureTask.run();» не может быть заменен старым методом? –

+0

Вы можете в основном объединить свои задачи, реализовав тот, который вызывает 'Thread.join()' на своем предшественнике (-ах), а затем делает все, что вам нужно. – Izruo

+0

Возможный дубликат [ждать, пока все потоки не закончат работу в java] (http://stackoverflow.com/questions/7939257/wait-until-all-threads-finish-their-work-in-java) –

ответ

0

Сохранить ссылки на резьбе, которые вы создали, и вызвать join()

Thread a = new Thread(task); 
Thread b = new Thread(task); 
a.start(); 
b.start(); 

a.join(); 
b.join(); 
//guaranteed that both threads have completed here 
+0

Он собирается заблокировать там, я хочу назвать эти потоки и забыть об этом, метод возвращает, и я ожидаю, что в обратном вызове последует. спасибо за то, что вы учите меня «присоединяться», хотя – user2727195

+0

@ user2727195 Лучше тогда использовать другой поток, затем запустить соединения и последующий обратный вызов – ControlAltDel

+0

ok, у вас есть точка. просто чтобы расширить знания здесь, знаете ли вы, что CompletableFuture и относится ли это к моему вопросу? – user2727195

0

В зависимости от того, сколько контроля вы хотите, вы можете использовать ThreadPoolExecutor:

tpe.execute (Runnable);

Ждать активного счета == 0;

затем выключение исполнителя.

Или сохранить нити в конструкции.

Wait для определенного TTL затем прервать их, если состояние Runnable

+0

справа. Кажется, isTerminated() может быть методом ожидания с этим. Я собирался добавить это к моему ответу, но думал, что это слишком усложнит ситуацию. – ControlAltDel

+0

Это зависит от того, как с ними нужно иметь дело. Я стараюсь избегать пулов, потому что я скорее сохраняю способность вытаскивать вилку, когда хочу – efekctive

+0

Если у вас есть «ThreadPoolExecutor», просто используйте 'invokeAll', чтобы отправить список задач и дождаться их завершения. Не нужно использовать kludges, как активный счетчик или выключение. – Holger

1

Один простой подход, чтобы отправить Runnable (ы) с ExecutorService, а затем вызвать shutdown, затем вызовите awaitTermination:

ExecutorService executor = Executors.newWorkStealingPool(); 
executor.submit(task); 
executor.submit(task); 

executor.shutdown(); 
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 

Не нужно использовать CompletableFuture.

+0

, можете ли вы сделать его другим абонентом и другим ответчиком, палач будет другим методом, а обратный вызов с результатом будет в другом. – user2727195

2

Предполагая, что ваш метод result() возвращает значение, которое вы хотите получить, то есть декларируется как Type result(), вы можете использовать

CompletableFuture<Type> f = CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> method1()), 
    CompletableFuture.runAsync(() -> method2()) 
).thenApply(_void -> result()); 

Каждый runAsync создает индивидуальный асинхронный CompletableFuture, который будет завершен один раз Runnable было казнены. Это то же самое, что и supplyAsync, за исключением того, что он не возвращает результат.

allOf создать CompletableFuture, который будет завершен, как только все указанные фьючерсы будут завершены, следовательно, любое зависящее от последовательности действие будет выполняться только после того, как все фьючерсы будут завершены. Используя thenApply, мы создаем зависимое будущее, которое будет завершено с возвращаемым значением result().

Если result() не предназначена для возврата значения, но только действие, которое должно выполняться после все остальные действия были завершены, вы можете использовать

CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> method1()), 
    CompletableFuture.runAsync(() -> method2()) 
).thenRun(() -> result()); 

вместо этого.

 Смежные вопросы

  • Нет связанных вопросов^_^