2016-04-28 11 views
0

私はマルチスレッドApache Tomcatサーブレットを作成しようとしています。このサーブレットは処理する各POST本体に大量のテキストを受け取り、GETリクエストを受け取ると受信した一意の単語の数。 QtとQtWebAppライブラリを使ってこれを達成することができましたが、これをJavaで実現することはできません。私はその問題が何であるか正確には分かっていませんが、おそらくアプリケーションの全体的なスレッドセーフティ(または単語がどのように分割され保存されているか)に関係しています。返される単語の数は常に高すぎます(実際の金額よりも2000〜4000倍高く、70000〜140000です。これらのテストケースの結果があります)。私のコードは以下の通りです:apache tomcatサーブレット内のjava HashSetのスレッドセーフ

@WebServlet(name = "data", urlPatterns =  {"/myserver/","/myserver/data","/myserver/count"}) 
public class data extends HttpServlet { 

HashSet<String> slova = new HashSet<>(); 
public final Lock lock = new ReentrantLock(); 

protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
     throws ServletException, IOException { 
    response.setContentType("text/html;charset=UTF-8"); 


    try (PrintWriter out = response.getWriter()) { 


     if("POST".equals(request.getMethod()) && "/osp/myserver/data".equals(request.getRequestURI())){ 

     InputStream body = request.getInputStream(); 
     GZIPInputStream gstream = new GZIPInputStream(body); 
     BufferedReader buffreader = new BufferedReader(new InputStreamReader(gstream, "UTF8")); 


     String vse =""; 
     StringBuffer sbuffer = new StringBuffer(); 

     while ((vse = buffreader.readLine()) != null) 
     { 
      sbuffer.append(vse); 
     } 

     String text = sbuffer.toString(); 
     System.out.println(text); 


      String[] words = text.split("\\s+"); 

      lock.lock(); 
      for(int i = 0; i < words.length; i++){ 

       slova.add(words[i]); 

      } 
      lock.unlock(); 

     } 
     if("GET".equals(request.getMethod()) && "/osp/myserver/count".equals(request.getRequestURI())){ 

      out.println(slova.size()); 
      slova.clear(); 
     } 

    } 
} 

何が原因なのでしょうか?どんなフィードバックも高く評価されます。私は要求に応じて、動作中のQtソースを投稿することができます。

+1

"GET"メソッドの処理ではコレクションが使用されますが、ロックは取得されません。それはおそらく問題です。組み込みのJavaコレクションは、特に明記されていない限り、スレッドセーフではありません。 – dsh

+2

私はinverseを期待しています。あなたのメソッドは、単語の数よりも少ない文字数を返します。その間にスペースを入れずに行を追加して、すべての行末の単語を次の行の最初の単語に連結します。メモリ内に巨大な文字列を作成し、その巨大な行を分割するのではなく、各行を分割するのはなぜですか?その多くの言葉で、私の推測はあなたが単に正確に数えられなかったということです。小さなサンプルを使用して、コードが期待どおりに機能することをテストしてください(スレッドセーフにした後) –

+0

ありがとうございます。 GETメソッドは、テストケースの最後に1回だけ受信されます。あなたが正しい間に、スレッドが安全でないことが原因でエラーが発生した場合、戻り値はそれ以上ではなくなります。 – user129186

答えて

0

JB Nizetに言及されている文字列分割が問題の根本でした。

関連する問題