2010-01-05 1 views
4

У меня есть длинная работа, выполняющаяся в фоновом режиме в пуле потоков ExecutorService. Каковы некоторые наилучшие методы с точки зрения этой задачи, возвращающие прогресс или промежуточные результаты? Существуют ли библиотеки, предоставляющие эту функциональность?Как я могу сообщить о прогрессе из фоновой задачи?

EDIT: Чтобы уточнить, я говорю о том, как сообщить о прогрессе другому коде, а не пользователю.

Обычно я использую SwingWorker, но я работаю с бэкэндом Java/Groovy для приложения Grails, и я не уверен, как это будет вести себя в безголовой серверной среде, поскольку имеет EDT-связи.

Другим примером является среда Jobs в Eclipse RCP, но мне нужно что-то, что не имеет связей с пользовательским интерфейсом.

+1

Не забудьте принять ответы - см. Http://meta.stackexchange.com/a/5235/165688 –

ответ

3

Эй, вы могли бы попробовать и реализовать шаблон наблюдателя и заинтересованные стороны подписываться на рабочий поток (расширение java.util.Observable или аналогичный) или другой класс, который управляет наблюдателями.

Вы можете использовать java.util.Observer и java.util.Observable или катить свои собственные.

Простой пример некоторых интерфейсов, реализующих шаблон Observer:

public interface ObservableSubject<T extends SubjectObserver, V> { 

    void registerObserver(T observer); 

    void removeObserver(T observer); 

    void notifyObservers(V notificationPayload); 

} 


public interface SubjectObserver<T> { 

    void handleNotification(T notificationPayload); 
} 

Подробнее: Observer Pattern on Wikipedia

1

Почему бы просто не использовать обратный вызов? При запуске фоновой задачи передайте объект с функцией обратного вызова в задачу и дайте этому отчет о задаче таким образом. Без какого-либо задействованного пользовательского интерфейса вам не нужно менять поток, чтобы сделать это.

0

Ответы от Адриана и edwardTheGreat оба хорошие варианты. Все зависит от того, как вы хотите, чтобы «другой код» потреблял обновления статуса. Третьим вариантом является использование очереди сообщений, в которую фоновый поток записывает периодический статус. На самом деле общая версия этого будет использовать JMS.

0

Я разработал простой интерфейс для этого:

public interface Process<TState, TResult> { 

    void onProgress(final Consumer<TState> callback); 

    void onCompletion(final Consumer<TResult> callback); 
} 

Использование как это:

final Process<Float, Either<IOException, String>> p = download(executor, url); 

p.onProgress(progress -> { 
    System.out.println("Progress: " + progress * 100); 
}); 

p.onComplete(result -> { 
    System.out.println("Finished: " + result.toString()); 
}); 

И в общей реализации, которая должна быть поточно-:

import com.google.common.base.Preconditions; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.function.Consumer; 

public final class SettableProcess<TState, TResult> implements Process<TState, TResult> { 

    private final Object LOCK = new Object(); 

    private final List<Consumer<TState>> progressCallbacks; 
    private final List<Consumer<TResult>> completionCallbacks; 

    private volatile boolean isComplete; 
    private volatile TResult result; 

    private SettableProcess() { 

     progressCallbacks = new ArrayList<>(); 
     completionCallbacks = new ArrayList<>(); 

     isComplete = false; 
     result = null; 
    } 

    @Override 
    public void onProgress(final Consumer<TState> callback) { 
     Preconditions.checkNotNull(callback); 
     if (!isComplete) { 
      synchronized (LOCK) { 
       if (!isComplete) { 
        progressCallbacks.add(callback); 
       } 
      } 
     } 
    } 

    @Override 
    public void onCompletion(final Consumer<TResult> callback) { 
     Preconditions.checkNotNull(callback); 
     synchronized (LOCK) { 
      if (isComplete) { 
       callback.accept(result); 
      } else { 
       completionCallbacks.add(callback); 
      } 
     } 
    } 

    public void complete(final TResult result) { 
     Preconditions.checkNotNull(result); 
     Preconditions.checkState(!isComplete); 
     synchronized (LOCK) { 
      Preconditions.checkState(!isComplete); 
      this.isComplete = true; 
      this.result = result; 
      for (final Consumer<TResult> callback : completionCallbacks) { 
       callback.accept(result); 
      } 
     } 
     completionCallbacks.clear(); 
     progressCallbacks.clear(); 
    } 

    public void progress(final TState state) { 
     Preconditions.checkNotNull(state); 
     Preconditions.checkState(!isComplete); 
     synchronized (LOCK) { 
      Preconditions.checkState(!isComplete); 
      for (final Consumer<TState> callback : progressCallbacks) { 
       callback.accept(state); 
      } 
     } 
    } 

    public static <TState, TResult> SettableProcess<TState, TResult> of() { 
     return new SettableProcess<>(); 
    } 
} 

Это может быть расширено для отмены отмены и т. Д.

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