3

Java でマルチ クライアント サーバー アプリケーションを使用しています。サーバーは接続を受信し続け、各クライアントは個別のスレッドによって処理されます。クライアント/サーバー通信は、ソケットが閉じられるまで続きます。そのため、クライアントから受信したリクエストは LinkedBlockingQueue に入れられ、他のスレッドがそのキューからの各リクエストを処理します。クライアント要求がキューに追加されるので、ConcurrentHashMap を使用して、後で要求が処理され、応答の準備ができたときに clientsocket を取得して、後でクライアントに応答を送信できるようにします。

ここで、タイムアウト機能を実装する必要があるため、リクエストが処理されず、応答が一定時間内に準備されていない場合、リクエストを現在処理できないというメッセージがクライアントに送信されます。マルチスレッド環境でそれを行うための最良のアイデアを教えてください。クライアント接続が各リクエスト ID に対して配置されるクライアント マップがあることを思い出してください。

マップキーを繰り返して時間をチェックする別のスレッドを用意することを考えています。しかし、リクエストがマップに追加され続けるので、それを行う最善の方法が必要です。

ありがとう

4

2 に答える 2

2

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 
        }
    }
};

リクエストをキューに入れ、①で説明したメソッドを実行することで、リクエストを並べ替えることができます。このメソッドは、まだタイムアウトしていないリクエストのみを実行することも処理します。追加のハウスキーピングは必要ありません。

于 2013-09-19T08:31:51.490 に答える
1

同時ハッシュ マップを使用します。これにより、読み取りの完全な同時実行と、書き込みの調整可能な同時実行が可能になります。揮発性変数を使用してデータを配置します。任意のスレッドによってバケットに対して何らかの変更が行われている場合でも、同じバケットからデータを読み取ろうとしている他のスレッドに表示されます。

于 2013-09-19T08:03:49.467 に答える