Guava の読み込みキャッシュは、タイムアウトと同時変更を解決できます: https://code.google.com/p/guava-libraries/wiki/CachesExplained次のように設定して、リクエスト マップを LoadingCache に交換します。
LoadingCache<Request, Connection> requests = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(1, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Request, Connection>() {
public Connection load(Request request) throws AnyException {
return clientConnectionForRequest(request);
}
});
リクエストが来ると、それをキャッシュにロードします。
requests.get(request);
この後、リクエストは処理されるのを待っています。処理が開始されたら、接続を取得してリクエストを無効にするため、キャッシュから削除されます。①</p>
Connection c = requests.getIfPresent(request);
if (c != null) {
requests.invalidate(request); // remove from the waiting area
// proceeed with processing the request
} else {
// the request was evicted from the cache as it expired
}
削除リスナーでは、エビクションをリッスンするいくつかの単純なロジックを実装する必要があります。(明示的に無効化すると、wasEvicted()
false が返されます。)
MY_LISTENER = new RemovalListener<Request, Connection>() {
@Override
public void onRemovaRequest RemovalNotification<Request, Connection> notification) {
if (notification.wasEvicted()) {
Connection c = notification.getValue();
// send timeout response to client
}
}
};
リクエストをキューに入れ、①で説明したメソッドを実行することで、リクエストを並べ替えることができます。このメソッドは、まだタイムアウトしていないリクエストのみを実行することも処理します。追加のハウスキーピングは必要ありません。