31

Spring サービスで定義された長時間実行タスクがあります。Spring MVC コントローラーによって開始されます。HttpResponseサービスを開始し、サービスが終了する前に呼び出し元に戻りたいです。サービスは最後にファイル システムにファイルを保存します。javascript で、サービスの状態を確認するためのポーリング ジョブを作成しました。

Spring 3.2 で注釈を見つけましたが、と@Asyncとの違いがわかりません。いつ使用する必要があり、いつ使用する必要がありますか?DeferredResultCallable@AsyncDeferredResult

4

3 に答える 3

24

Asyncはメソッドにアノテーションを付けて、非同期的に呼び出されるようにします。

@org.springframework.stereotype.Service
public class MyService {
    @org.springframework.scheduling.annotation.Async
    void DoSomeWork(String url) {
        [...]
    }
}

したがって、Spring はそれを実行できるため、実行方法を定義する必要があります。例えば:

<task:annotation-driven />
<task:executor id="executor" pool-size="5-10" queue-capacity="100"/>

このように service.DoSomeWork("parameter") を呼び出すと、呼び出しはエグゼキューターのキューに入れられ、非同期で呼び出されます。これは、同時に実行できるタスクに役立ちます。

Async を使用して、あらゆる種類の非同期タスクを実行できます。定期的にタスクを呼び出したい場合は、@Scheduled を使用できます(また、task:executor の代わりに task:scheduler を使用します)。これらは、Java Runnables を呼び出す簡単な方法です。

DeferredResult<>は、応答に使用される Tomcat HTTP スレッドをブロックすることなく、請願に応答するために使用されます。通常は、ResponseBody アノテーション付きメソッドの戻り値になります。

@org.springframework.stereotype.Controller
{
    private final java.util.concurrent.LinkedBlockingQueue<DeferredResult<String>> suspendedRequests = new java.util.concurrent.LinkedBlockingQueue<>();

    @RequestMapping(value = "/getValue")
    @ResponseBody
    DeferredResult<String> getValue() {
            final DeferredResult<String> result = new DeferredResult<>(null, null);
            this.suspendedRequests.add(result);
            result.onCompletion(new Runnable() {
            @Override
            public void run() {
        suspendedRequests.remove(result);
            }
});
            service.setValue(result); // Sets the value!
            return result;
    }
}

前の例には 1 つの重要な点が欠けており、遅延結果がどのように設定されるかが示されていません。他のメソッド (おそらく setValue メソッド) には、result.setResult(value) があります。setResult への呼び出しの後、Spring は onCompletion プロシージャを呼び出し、HTTP 要求への応答を返します ( https://en.wikipedia.org/wiki/Push_technology#Long_pollingを参照)。

しかし、setValue を同期的に実行しているだけの場合、遅延結果を使用しても利点はありません。ここで Async の出番です。非同期メソッドを使用して、別のスレッドを使用して将来のある時点で戻り値を設定できます。

    @org.springframework.scheduling.annotation.Async
    void SetValue(DeferredResult<String> result) {
        String value;
        // Do some time consuming actions
        [...]
        result.setResult(value);
    }

遅延結果を使用するために非同期は必要ありません。これは、それを行う 1 つの方法にすぎません。

この例では、延期された結果のキューがあります。たとえば、スケジュールされたタスクは、保留中の要求を処理するために監視できます。また、非ブロッキング メカニズム ( http://en.wikipedia.org/wiki/New_I/Oを参照) を使用して、戻り値を設定することもできます。

全体像を完成させるために、Java 標準先物 ( http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html ) および呼び出し可能オブジェクト ( http:// docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html ) は、Spring DeferredResult および Async と多少同等です。

于 2013-08-08T08:24:23.723 に答える
5

DeferredResultServlet 3.0 AsyncContext を利用します。結果が返される必要がある場合、他のスレッドのようにスレッドをブロックしません。

もう 1 つの大きな利点は、DeferredResultコールバックがサポートされていることです。

于 2013-07-25T11:59:58.550 に答える