У меня есть следующий код Java:
final Future future = exeService.submit(
new Runnable() {
public void run() {
myObject.doSomething();
}
}
);
future.get();
где exeService
экземпляр
java.util.concurrent.ExecutorService
Проблема - это myObject.doSomething()
никогда возвраты, и, следовательно, future.get()
никогда возвраты.
Однако, если я заменяю вызов к submit
с вызовом к execute
как это:
exeService.execute(
new Runnable() {
public void run() {
myObject.doSomething();
}
}
);
вызов к myObject.doSomething()
действительно возвращается. Я не знаю, имеет ли это значение, но doSomething()
a void
метод.
Почему doSomething()
окончание при использовании execute
но не при использовании submit
?
Кроме того, я не должен использовать Future.get()
; это просто, казалось, было самым естественным способом сделать это. (Я также сталкиваюсь с той же проблемой с CountdownLatch
.) Дело в том, что я должен ожидать doSomething()
для окончания перед продолжением, и, по сложным причинам, в которые я не войду здесь, я должен запустить его на отдельном потоке. Если бы существует другой способ сделать это, которое работает, который был бы прекрасен.
Как в Executor.execute () Javadoc :
Выполняет заданную команду через некоторое время в будущем. Команда может выполняться в новом потоке, в объединенном потоке или в вызывающем потоке по усмотрению реализации Executor .
Таким образом, метод execute ()
немедленно возвращает, не оставляя вам возможности запросить статус отправленной задачи.
С другой стороны ExecutorService.submit () :
Отправляет Runnable задачу на выполнение и возвращает Future, представляющий эту задачу. Метод get Future вернет null после успешного завершения .
Future.get () вернет только после успешного завершения, поэтому никогда в вашем случае.
Это дополнительно указано в документации Future.get () :
Ожидает, если необходимо, завершения вычисления , а затем получает его результат .
Я создал SSCCE:
package com.stackoverflow.q2585971;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main(String args[]) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = executor.submit(
new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Epic fail.");
}
}
}
);
System.out.println("Waiting for task to finish..");
future.get();
System.out.println("Task finished!");
executor.shutdown();
}
}
Он работает совершенно нормально. Сначала печатается
Waiting for task to finish..
затем через секунду вы видите
Task finished!
Так что ваша проблема кроется где-то в другом месте. Я продублирую свой комментарий к вашему вопросу здесь:
Ваш вопрос довольно запутанный. Первая конструкция должна работать. Путаница в слове "возвращение". Разве вы не имеете в виду "завершение" или "выполнение"? Ваша путаница, похоже, основана на том, что
future.get()
фактически ожидает завершения runnable и, таким образом, блокирует поток и не дает ему выполнить остаток кода после строкиfuture.get()
.
Проверить наличие взаимоблокировок в doSomething
.
Я бы начал с поиска вызовов ожидания
.
Если вы ждете
чего-то, вам нужно сигнализировать ожидаемому объекту из другого потока, вызвав notify
или notifyAll
.