JAX-RSでは、@Suspend
注釈とAsyncResponse
は、特定の典型的なシナリオでのみ必要です。最初のシナリオは、コード例ですでに識別されています。これは長時間実行されるタスクです。この場合、AsyncResponse
を使用して、バックグラウンドスレッドで長期実行コードを実行することができます。一見するとこれは意味をなさないが、アプリケーションサーバー/コンテナが要求をどのように処理するかについて考える必要がある。通常、クライアント要求を受け入れて処理するスレッドのプールがあります。 JAX-RSサービスメソッドで高価なオペレーションをインラインで実装すると、プール内のスレッドの1つが実行時全体でブロックされます。 AsyncResponse
を使用すると、エグゼキュータ・スレッドがプールに戻され、他のリクエストを並行して処理できます。
@Path("/users")
public class UserRestService {
@GET
public void getAllUsers(@Suspend final AsyncResponse asyncResponse) {
new Thread(new Runnable(
@Override
public void run() {
List<Users> users = UserDAO.loadAllUsers();
asyncResponse.resume(users);
}
) {}).start();
}
}
AsyncResponse
ための第二のアプリケーション・シナリオでは、プロデューサ、コンシューマパターンのしばしば見られるパターンです。キューhttps://yourservice.at/queue/next
にバインドされているキューがあるとしたら、@GET
メソッドをブロックtake()
に使用すると、LinkedBlockingQueue
と言うことができます。同じURLには、@POST
メソッドをバインドして、データをキューに追加することができます。この場合、AsyncResponse
にtake()
操作の機能をまとめます。これらの説明から、
@Path("/queue/next")
public class MessageQueueService {
private static final LinkedBlockingQueue<AsyncResponse> suspendedResponses = new LinkedBlockingQueue<AsyncResponse>();
@GET
public void getNextMessage(@Suspend final AsyncResponse asyncResponse) {
MessageQueueService.suspendedResponses.put(asyncResponse);
}
@POST
public void putNewMessage(final String message) throws InterruptedException {
AsyncResponse asyncResponse = suspendedResponses.take(); // note how this could also block a thread
asyncResponse.resume(message);
}
}
あなたはまた、JAX-RS @Suspended
メカニズムは、非同期サーバー側のタスクを作成するために使用されていることを、見ることができます。クライアント上で同じリクエストが非同期で実行されるかどうかは、まったく別の話です。
いいえ、クライアント側の非同期はサーバー側で非同期を意味するわけではありません。逆もまた同様です。 – EJP
長時間実行されているタスクではサーバー上でasyncを使用して、コンテナスレッドを保持しないようにする必要があります。 –