5

ExecutorServiceスレッドプールのバックグラウンドで実行されている長時間実行タスクがあります。進捗状況または中間結果を返すこのタスクに関するいくつかのベストプラクティスは何ですか?この機能を提供するライブラリはありますか?

編集:明確にするために、私は進行状況をユーザーではなく他のコードに報告することについて話している。

通常はSwingWorkerを使用しますが、GrailsアプリのJava / Groovyバックエンドを使用しており、EDTとの関係があるため、ヘッドレスサーバー環境でどのように動作するかわかりません。

もう1つの例は、Eclipse RCPのJobsフレームワークですが、UIとは関係のないものが必要になります。

4

4 に答える 4

0

Adrian と edwardTheGreat からの回答はどちらも良い選択肢です。それはすべて、「他のコード」がステータス更新をどのように消費するかによって異なります。3 番目のオプションは、バックグラウンド スレッドが定期的なステータスを書き込むメッセージ キューを使用することです。これの非常に一般的なバージョンでは、JMS を使用します。

于 2010-01-05T03:42:09.697 に答える
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<>();
    }
}

これは、キャンセルなどをサポートするために拡張できます。

于 2017-05-23T15:18:56.383 に答える