6

Javaサーブレットでいくつかのタスク(ほとんどの場合、リクエストパラメータを使用して複数の外部URLを呼び出し、データを読み取る)を実行し、数秒以内にユーザーに応答を送信する必要があります.ExecutorServiceを使用して同じことを達成しようとしています. doGet メソッドのユーザー リクエストごとに 4 つの FutureTask を作成する必要があります。各タスクは約 5 ~ 10 秒実行され、ユーザーへの合計応答時間は約 15 秒です。

Java サーブレットで ExecutorService を使用する場合、次の設計のうちどれが優れているか教えてください。

1)(リクエストごとに newFixedThreadPool を作成し、できるだけ早くシャットダウンする)

public class MyTestServlet extends HttpServlet
{

    ExecutorService myThreadPool = null;

    public void init()
    {
          super.init();

    }
    protected void doGet(HttpServletRequest request,HttpServletResponse response)
    {

        myThreadPool = Executors.newFixedThreadPool(4);
        taskOne   = myThreadPool.submit();
        taskTwo   = myThreadPool.submit();        
        taskThree = myThreadPool.submit();
        taskFour  = myThreadPool.submit();

        ...
        ...

        taskOne.get();
        taskTwo.get();
        taskThree.get();
        taskFour.get();

        ...

        myThreadPool.shutdown();


    }

     public void destroy()
     {

         super.destroy();
     }

}

2) (サーブレットの初期化中に newFixedThreadPool を作成し、サーブレットの破棄時にシャットダウンする)

public class MyTestServlet extends HttpServlet
{

    ExecutorService myThreadPool = null;

    public void init()
    {
      super.init();
          //What should be the value of fixed thread pool so that it can handle multiple   user requests without wait???
          myThreadPool = Executors.newFixedThreadPool(20);

    }
    protected void doGet(HttpServletRequest request,HttpServletResponse response)
    {


        taskOne   = myThreadPool.submit();
        taskTwo   = myThreadPool.submit();        
        taskThree = myThreadPool.submit();
        taskFour  = myThreadPool.submit();

        ...
        ...

        taskOne.get();
        taskTwo.get();
        taskThree.get();
        taskFour.get();

        ...



    }

     public void destroy()
     {

          super.destroy();
          myThreadPool.shutdown();
     }

}

3) (サーブレットの初期化中に newCachedThreadPool を作成し、サーブレットの破棄時にシャットダウンする)

public class MyTestServlet extends HttpServlet
{

      ExecutorService myThreadPool = null;

      public void init()
      {
        super.init();
            myThreadPool = Executors.newCachedThreadPool();

      }
      protected void doGet(HttpServletRequest request,HttpServletResponse response)
      {


          taskOne   = myThreadPool.submit();
          taskTwo   = myThreadPool.submit();        
          taskThree = myThreadPool.submit();
          taskFour  = myThreadPool.submit();

          ...
          ...

          taskOne.get();
          taskTwo.get();
          taskThree.get();
          taskFour.get();

          ...




     }

     public void destroy()
     {

            super.destroy();
            myThreadPool.shutdown();
      }

}
4

2 に答える 2

1

最初のものはオプションであってはなりません。スレッド プール (およびおそらくすべてのプール) の考え方は、プール メンバー (この場合はワーカー スレッド) の構築に必要なオーバーヘッドとメモリを最小限に抑えることです。そのため、一般に、アプリケーションの起動時にプールを初期化し、シャットダウン時に破棄する必要があります。

2 と 3 の選択については、次の投稿で受け入れられた回答を確認してください。答えは違いを説明しており、どちらがニーズに適しているかを判断できます: newcachedthreadpool-vs-newfixedthreadpool

于 2012-08-02T21:56:24.080 に答える
0

要求ごとにスレッド プールを作成して破棄するのは、悪い考えです。費用がかかりすぎます。

各 URL フェッチ タスクがどの HTTP 要求に関連しているかを覚えておく方法がある場合は、CachedThreadPool を使用します。URL フェッチ タスクは完全に独立しており、(CPU やメモリに依存するのではなく) ネットワークに依存するため、オンデマンドで拡張および縮小する機能は驚くべきものです。

また、ThreadPool を CompletionService でラップすると、送信順序に関係なく、ジョブが完了するたびに通知を受け取ることができます。初完成、初告知。これにより、より速いジョブがすでに完了している場合に、遅いジョブでブロックされないようになります。

CompletionService は簡単に使用できます。既存の ThreadPool (newCachedThreadPool など) をラップし、それにジョブを submit() してから、結果を take() します。take() メソッドがブロックしていることに注意してください。

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CompletionService.html

于 2012-08-02T22:47:22.660 に答える