5

これはマルチスレッド Java アプリケーションの一般的なシナリオだと思うので、ここで説明します。

私の Java アプリには、 5 つのスレッドのプールを定義するthreadExecutorオブジェクトがあります。

ExecutorService threadExecutor = Executors.newFixedThreadPool(5);

sendCallablesメソッドは、ジョブのリストを Executor に割り当てる責任がありますObjectXを使用してList
追跡します。このようにして、ユーザーがスレッドを中断/キャンセルしたい場合に、Future のリストを参照することができます。このようなもの:

Map<ObjectX, List<Future<String>>> map = new HashMap<ObjectX, Future<String>>();

public void sendCallables(ObjectX referenceObj, List<Callable<String>> list) {
    ...
    List<Future<String>> futureList = new ArrayList<Future<String>>();
    for(Callable<String> myCallableJob : list) {
        Future<String> future = threadExecutor.submit(myCallableJob);
        futureList.add(future);
    }
    ...
    map.add(referenceObj, futureList);
    ...
}

public void cancelFutures(ObjectX referenceObj) {
    ...
    List<Future<String>> list = map.get(referenceObj);
    for(Future<String> future : list) {
        future.cancel();
    }
    map.remove(referenceObj);
    ....
}

ここまでは順調ですね。

提出されたタスクを実行する必要がなくなった場合があります。
このような状況では、タスクをキャンセルする決定は、アプリケーションによってインテリジェントに/自動的に行われる必要があります。
このようなケースの例は、ユーザーのセッションが期限切れになったとき、またはすべてのジョブが実行される前に特定のフロー (送信されたタスクに関連する) が終了したときの Web アプリケーションで見つけることができます。

したがって、基本的に、アプリケーションがジョブを実行し続ける意味がない場合は、毎回 cancelFutures(referenceObj) を呼び出す必要があります。アプリケーションがそれを呼び出す必要がある場合は、それぞれの状況を特定する必要があります。

これを行うためのより良いアプローチがあるかどうか疑問に思っています。

アプリケーションによって referenceObj が参照されなくなったら、 WeakHashMapでマップをクリーンアップできるように考えていましたが、まだ .cancel() を呼び出す必要があるため、Future の実行を停止しません (一種のWeakHashMap remove(Object) メソッドに関連付けられた eventHandler ? )

4

2 に答える 2

3

あなたが提案している解決策はかなり良いと思います。本当にガベージ コレクションを取得する referenceObj からキャンセルを実行したい場合は、WeakReference と ReferenceQueue を組み合わせて使用​​できます。

これらのいずれかを実行ヘルパー クラスで宣言します。

ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>();

タスク バッチが送信されるたびにこれを行う

new WeakReference<ObjectX>( referenceObj, refQ ).enqueue();

このループを実行するだけのスレッドを用意します。このループは、到達が困難になった (GC の対象となる) オブジェクトをプルオフし、先物/タスクをキャンセルします。

while (true)
{
    // this blocks
    ObjectX referenceObj = refQ.remove().get();
    cancelFutures( referenceObj );
}
于 2010-03-26T14:52:24.157 に答える
0

私があなたの問題を正しく理解していれば、さまざまな種類のアクティビティが発生しており、キャンセルできるという理由だけでこれらのアクティビティを結び付けたくはありません。

私には、キャンセルが必要な各ケースがイベントをトリガーする必要があるように思えます。イベント リスナーはこれらのイベントをリッスンし、関連をキャンセルしますFuture

セッションに関する例 - を実装しjavax.servlet.http.HttpSessionListner、キャンセルが必要な関連タスクを検出し、イベントを発生させてそれらのタスクをキャンセルするクラスがあります。すべてが非同期であるため、キャンセルされたタスクが終了したかどうかは気にしないため、何も失われません。

于 2010-03-26T14:42:21.440 に答える