2010-01-05 41 views
4

我有一个在ExecutorService线程池的后台执行的长时间运行的任务。根据这项任务返回进度或中间结果,有哪些最佳做法?有没有提供这种功能的库?如何报告后台任务的进度?

编辑:为了澄清,我正在谈论报告进展到其他代码,而不是用户。

通常情况下,我会使用SwingWorker,但我正在为Grails应用程序使用Java/Groovy后端,并且我不确定它如何在无头服务器环境中运行,因为它具有EDT关系。

另一个例子是Eclipse RCP中的Jobs框架,但我需要一些与UI无关的东西。

+1

请记住接受答案 - 请参阅http://meta.stackexchange.com/a/5235/165688 – 2012-05-17 10:32:39

回答

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

从Adrian和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<>(); 
    } 
} 

这可以扩展为支持取消等。