1

GUIがフリーズするのを防ぐために、新しいスレッドでサーバー呼び出しを管理しているJavaクライアントがあります。

これが多くの場所で防止されたとしても、たとえば異なるパラメーターを使用して、同じモデルでメソッドが再度呼び出される可能性があります。そのような場合、私は明らかに、最新のパラメーターを使用した最新の呼び出しが「成功」し、その結果を表示することを望んでいます。

以前に起動されたスレッドを追跡し、新しいスレッドを起動する前に中断するシステムがあります ( Thread.interrupt())。if (Thread.currentThread().isInterrupted()他のメソッドは、新しい結果を GUI 要素に送信する前に( を使用して) 中断されないスレッドで実行されているかどうかを確認します。

この構造は、サーバーへの以前のコネクタで機能していました。プロセスの割り込みフラグをチェックしていたのは私だけだったからです。私の問題は、現在クライアントで EJB メソッド呼び出しを使用していて、中断されたスレッドに対する反応が悪いことです。EJB 呼び出し中にスレッドを中断すると、RuntimeExceptionを含むがトリガーされInterruptedExceptionます。そして、それは普通のことではないようです。

明らかに、すべてのサーバー呼び出しで RuntimeExceptions をキャッチし、割り込みの原因を確認できますが、あまり「クリーン」ではないようです。

私の質問は、そのような状況で何ができるでしょうか? EJB メソッド呼び出しを実行しているスレッドを中断する適切な方法は何ですか?

4

3 に答える 3

1

廃止された EJB 呼び出しがサーバー上で継続することを気にしないのであれば、呼び出し元のスレッドが「自然に」終了することを許可するのではなく、その呼び出しが別のスレッドによって置き換えられたために結果を破棄しないのはなぜですか? サンプルの実装を提供する時間はありませんが、Futures および関連する Java 並行処理クラスを使用すると、ある程度の成果が得られることに気付くかもしれません。

編集

これに加えて、このようなものでうまくいくかもしれませんが、私にはハックに感じられ、もっとエレガントなソリューションがあると確信しています.

呼び出しスレッド (おそらくボタンの onclick メソッド) で:

AsynchronousResultManager.registerRequest("UNIQUE_IDENTIFIER", runnableExecuteRequest);

は次のregisterRequestようになります。

registerClick(String id, Runnable execution) {
    AtomicReference ref = executions.get(id); //executions is a Map<String, AtomicReference> created as a a computing map by Guava MapMaker
    execution.setReference(ref); //so that the Runnable has a reference to it later
    ref.set(execution); //this will overwrite an existing reference to a previous invocation.
    //here you need to actually kick off your thread in whatever way works best for you
}

runnableリクエストを実行する は、次のサブクラスになります。

public abstract class RequestRunnable implements Runnable {

    private AtomicReference ref;

    public void run() {
        doRunInternal(); //actually go off and do the request to the J2EE server
        if (this == ref.get()) { //ie if the current runnable is the same as in the reference, we can proceed to actually dispatch the result
            dispatchResult(); //this method would do something like add a runnable to the SwingWorkerThread
        }
    }

    protected abstract void doRunInternal();
    protected abstract void dispatchResult();

    public void setReference(AtomicReference ref) {
        this.ref = ref;
    }

}

これはおそらくクラッシュして燃えるでしょうが、うまくいけば、お問い合わせの行を示しています...

于 2011-03-08T11:31:31.153 に答える
0

スレッドを停止するには、2種類のアクションを実行する必要があります。

  • スレッドがブロッキング操作(IO、ネットワーク、ロックなど)を待機している場合は、スレッドを中断する必要があります。InterruptedExceptionがスローされ、実行中のコードが例外をキャッチして適切な方法で停止する機会を与えます。
  • スレッドが何らかの処理を行っているだけの場合、Thread.interrupt()は役に立ちません。例外はスローされず、スレッドは単に処理を続行します。処理コードは、プロセスを続行する必要があることを定期的に確認する必要があります。

いずれにせよ、それを適切に行うには、停止したいスレッドによって実行されるコードが両方の場合に対処する必要があります。ここには特効薬はありません。

于 2011-03-08T10:54:45.567 に答える
0

既存のアーキテクチャを考慮して、最終的に次のような形式で、各サーバー呼び出しから RuntimeException をキャッチしました。

try {
    return getEJBService().getServiceResult(param, param, param);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof InterruptedException)
        throw (InterruptedException)cause;
    else
        throw e;
}

あまりきれいではありませんが、少なくとも現在のモデルで中断に応じて行動することができます.

理想的な世界では、Rich提供するソリューションのいずれかを使用する必要があります。

于 2011-03-14T09:52:01.880 に答える