java.util.concurrent. Future.get () не возврат

У меня есть следующий код 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() для окончания перед продолжением, и, по сложным причинам, в которые я не войду здесь, я должен запустить его на отдельном потоке. Если бы существует другой способ сделать это, которое работает, который был бы прекрасен.

5
задан Paul Reiners 6 April 2010 в 15:26
поделиться

3 ответа

Как в Executor.execute () Javadoc :

Выполняет заданную команду через некоторое время в будущем. Команда может выполняться в новом потоке, в объединенном потоке или в вызывающем потоке по усмотрению реализации Executor .

Таким образом, метод execute () немедленно возвращает, не оставляя вам возможности запросить статус отправленной задачи.

С другой стороны ExecutorService.submit () :

Отправляет Runnable задачу на выполнение и возвращает Future, представляющий эту задачу. Метод get Future вернет null после успешного завершения .

Future.get () вернет только после успешного завершения, поэтому никогда в вашем случае.

Это дополнительно указано в документации Future.get () :

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

16
ответ дан 18 December 2019 в 06:22
поделиться

Я создал 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().

7
ответ дан 18 December 2019 в 06:22
поделиться

Проверить наличие взаимоблокировок в doSomething .

Я бы начал с поиска вызовов ожидания .

Если вы ждете чего-то, вам нужно сигнализировать ожидаемому объекту из другого потока, вызвав notify или notifyAll .

0
ответ дан 18 December 2019 в 06:22
поделиться