1

Tomcat Web サーバーにデプロイされたステートレス Java アプリケーションがあります。データの性質上、常にすべての http スレッドが異なるキーを処理する必要があります (つまり、すべてのスレッドが異なるキーを処理する必要があります)。

したがって、リクエストのキーが現在進行中の場合に http ポストをキューに入れるモジュールを作成しました (この前の http ポストによって)。同じキーを持つ以前の http 投稿が処理を完了した場合にのみ、現在の http 投稿の処理を続行します。

進行中の同じキーを持つ以前のリクエストがあるかどうかをテストするために、concurrenthashmap を使用した単純な while ループを作成しました。パフォーマンスは標準以下で、予期しない動作があります。これはコード スニペットです。

//This part of code is place inside the servlet 
private static ConcurrentHashMap<String, String> transQueue = new ConcurrentHashMap<String, String>();
private void inQueuePoll(String queueKey) {
   while(transQueue.containsKey(queueKey)){     
      synchronized(this){
         try{
            Thread.sleep(50); // i know this is bad, any idea to improve this?
            logger.trace("Wait for Que Key: "+queueKey + " );

            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    transQueue.put(queueKey, "");
}

各 http 投稿の最後に、finally ブロックに次のように入力しました。しかし、私の最悪の悪夢では、サーバー ログから、別の http ポスト スレッドである queueKey を削除する前に、なんとか上記の while ループから抜け出し、処理を続行していることに気付きました。

httpスレッドを「キューに入れる」ために上記のコードで間違ったことはありますか?

また、これをより良く行う方法についてのアイデアも大歓迎です。

4

1 に答える 1

0

まず、明確にするためにあなたのケースをもう一度述べていただければ幸いです。特定のキーに対して、すべてのリクエストは単一のスレッドで処理する必要があります。ただし、他のキーのリクエストは、最初のキーのリクエストの処理と同時に処理される場合があります。

これはExecutorServiceにぴったりだと思います。マップをマップにします。キーはキュー キーで、値はシングルスレッド エグゼキュータです ( Executors.newSingleThreadExecutor()<String, ExecutorService>で取得できます)。

キーを指定するExecutorServiceと、マップから を取得し、Callableを送信して処理します。このキーの はシングル スレッドであるため、Executorこのキーが処理される前に、そのキーの前の要求が処理されるまで待機することが保証されます。getの呼び出しは、このリクエストの処理が完了するまでブロックされます。

于 2011-11-01T15:09:39.527 に答える