Подтвердить что ты не робот

Способность добиться прогресса на объекте Future <T>

Что касается пакета java.util.concurrent и интерфейса Future, я замечаю (если не ошибаюсь), что возможность запускать длительные задачи и иметь возможность запрашивать прогресс только с классом реализации SwingWorker.

Это вызывает следующий вопрос:

Есть ли способ в не-GUI, не-Swing-приложении (для создания консольного приложения), чтобы запустить длинную задачу в фоновом режиме и разрешить другим потокам проверять прогресс? Мне кажется, что нет причин, по которым эта возможность должна ограничиваться приложениями swing/GUI. В противном случае единственный доступный вариант, как я его вижу, - это пройти через ExecutorService:: submit, который возвращает объект Future. Однако базовый интерфейс Future не позволяет контролировать прогресс.

4b9b3361

Ответ 1

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

Объект Runnable или Callable, который вы отправляете, должен знать, как обеспечить этот прогресс (процент завершен, количество попыток, статус (enum?) и т.д.) и предоставить это как вызов API самому объекту или отправленный в некотором ресурсе поиска (в случае необходимости в карте памяти или базе данных). Для простоты я склоняюсь к самому объекту, тем более, что вам, скорее всего, понадобится дескриптор (id) для поиска объекта или ссылки на сам объект.

Это означает, что у вас есть 3 потока. 1 для фактической работы 1, которая заблокирована во время ожидания результата, и 1, который является потоком мониторинга. Последнее можно разделить в зависимости от ваших требований.

Ответ 2

Я надеялся, что существует стандартный способ concurrency, чтобы оставаться в курсе прогресса долговременной задачи, не требуя, чтобы клиентская программа беспокоилась о правильной настройке и синхронизации. Мне показалось, что можно понять расширенный вариант интерфейса Future<T>, который будет поддерживать: public short progress(); в дополнение к обычным методам isDone() и get(). Очевидно, что реализация progress() затем должна была бы опросить объект напрямую, поэтому, возможно, Future<T> нужно будет указать как Future<T extends CanReportProgress>, где CanReportProgress - это следующий интерфейс:

public interface CanReportProgress {
    public short progress();
}

Это ставит вопрос о том, почему можно было бы пройти через объект Future, а не вызывать сам объект, чтобы получить прогресс. Я не знаю. Мне придется больше подумать. Можно утверждать, что он ближе к текущему контракту/семантике, в результате чего объект Callable не сам снова обращается к клиентскому программисту после вызова ExecutorService::submit/execute.

Ответ 3

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