2016-08-09 8 views
0

私は、非同期要求をファイアー・アンド・ファッションで実行できるメソッドを持っています。非同期処理のために短命のExecutorService

方法は、次のように実装されています

private void publishWorkItem(final Object payload, final ZkWorkCompleteCallback callback) 
{ 
    if (payload == null) 
     throw new NullPointerException(); 

    final ExecutorService executor = Executors.newSingleThreadExecutor(PUBLISH_WORK_THREAD_FACTORY); 

    try 
    { 
     executor.execute(() -> { 

      try 
      { 
       if (callback != null) 
       { 
        final ZkWorkItem retval = publishWorkItem(payload); 
        callback.onCompleted(retval); 
       } 
      } 
      catch (final InterruptedException e) 
      { 
       // suppressed 
      } 
      catch (final Exception e) 
      { 
       LOGGER.error("Unhandled exception", e); 

       if (callback != null) 
        callback.onError(e); 
      } 
     }); 
    } 
    finally 
    { 
     executor.shutdown(); 
    } 
} 

問題は、私は、各非同期リクエストのための新しいExecutorServiceのExecutors.newSingleThreadExecutorを作成する代わりに、固定のスレッドプールを使用していますということです。その理由は、publishWorkItem(payload)メソッドがCountDownLatch#await()を使用し、Watcherが終了するのを待つので、実行中のスレッドをブロックするということです。これは、固定サイズのプールをすぐに使い果たすことがあります。 publishWorkItem(payload)

final CountDownLatch latch = new CountDownLatch(1); 

     zkClient.exists(pathToWatch, new Watcher() 
     { 
      @Override 
      public void process(final WatchedEvent event) 
      { 
       try 
       { 
        extractAndDelete(baos, event.getPath()); 
       } 
       catch (final Exception e) 
       { 
        LOGGER.error("Unable to perform cleanup", e); 
       } 
       finally 
       { 
        latch.countDown(); 
       } 
      } 
     }, true); 

     ------ THIS IS THE PROBLEM (Blocks current thread) ------ 
     latch.await(); 

簡体字コードは、だから私の質問は:そこにこの種の問題へのより良いアプローチです。

私はアプリケーションをプロファイルしましたが、パフォーマンス上の問題はありませんでした。懸念事項は、スレッドが多数作成されていることでした。

+0

サイドノート:単純なone-linerでnullのthrowを置き換えることができます: 'Objects.requireNonNull(theObject、" theObjectはnullでないはずです) " – GhostCat

+1

あなたのことははっきりしないので、ここで達成しようとしています。 ZKでやっていることに共通のパターンがあるかもしれないので、いくらか冗長な現在のタグの1つ以上を削除し、[zookeeper]を追加することは価値があるかもしれません。 ZK開始者ではありません。 –

答えて

0

なぜExecutorService.newCachedThreadPool()を使用しないのですか? javadocツールによれば、これらのプールは、通常、多くの短命の非同期タスクを実行するプログラムのパフォーマンスを向上させるあなたのユースケース

に合った利用可能

場合...以前に構築スレッドを再利用します

publishWorkItem()の呼び出しごとに新しいシングルスレッドプールを作成する代わりに、キャッシュされたスレッドプールを1回作成してすべてのクエリに使用します。スレッド数はInteger.MAX_VALUEで制限されているため、固定スレッドプールのように制限されることはありませんが、全体的にスレッドを少なくする必要があります。

+0

これは私がやったことです。 – Greg