java.util.concurrent.Future.get () не возвращается - PullRequest
4 голосов
/ 06 апреля 2010

У меня есть следующий код 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() - это void метод.

Почему doSomething() заканчивается при использовании execute, а не при submit?

Кроме того, мне не нужно использовать Future.get(); Казалось, это самый естественный способ сделать это. (Я также сталкиваюсь с той же проблемой с CountdownLatch.) Суть в том, что мне нужно дождаться завершения doSomething(), прежде чем продолжить, и по сложным причинам я не буду вдаваться в подробности, мне нужно запустить отдельная тема. Если есть другой способ сделать это, это будет хорошо.

Ответы [ 4 ]

15 голосов
/ 06 апреля 2010

Как и в Executor.execute () Javadoc :

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

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

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

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

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

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

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

7 голосов
/ 06 апреля 2010

Я создал 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() фактически ожидает завершения работоспособного объекта и, таким образом, заблокирует поток и не позволит ему выполнить остаток кода после строки future.get().

2 голосов
/ 27 марта 2014

Java фьючерсы блокируют! get(). This method blocks the current thread until a future instance completes its work, thus requiring the use of one thread more than the work that must be performed just to manage what happens when it is done

0 голосов
/ 06 апреля 2010

Проверьте наличие тупиков (ы) в doSomething.

Я бы начал с поиска wait звонков.

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

...