2016-09-14 7 views
0

次のコードを検討してください。他のタイマーイベントがハングした場合、ScheduledThreadPoolExecutorタイマーは起動しません。

import java.util.concurrent.ScheduledThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 


public class Test { 
    private static ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(0); 

    public static void onTimer() { 
     System.out.println("onTimer"); 
     while (true) { 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException ignored) { 
      } 
     } 
    } 

    public static void onTimer2() { 
     System.out.println("onTimer2"); 
    } 

    public static void main(String[] args) { 
     threadPool.scheduleAtFixedRate(Test::onTimer, 0, 500, TimeUnit.MILLISECONDS); 
     threadPool.scheduleAtFixedRate(Test::onTimer2, 0, 500, TimeUnit.MILLISECONDS); 
    } 
} 

固定レートでスケジュールされた2つのタイマーがあり、最初のタイマーイベントでは、タスクが無期限にハングします。それはそれは望んでいる限り多くのスレッドを作成することが許可されているスレッドプールを使用して作成されているので、最初のタスクがハングアップしていても

は、私は、第二のタイマは特定の速度で発射することを期待しています。

しかし、第二タイマーが発火することはありません。

誰かが理由を説明できますか?

+0

スレッドプールサイズが0であるため、スレッドプールサイズを2以上に増やしてからもう一度試してください。 –

+0

@SangramJadhav 0はスレッドプールの初期サイズです。ドキュメントによれば、プールは必要に応じて拡大することができます。 –

+0

@SangramJadhavはそれについてコメントしようとしていましたが、それは無関係のようです。プールサイズを最初に0に設定して、複数の並行タスクをスケジュールすることができます。 – Mena

答えて

2

ScheduledThreadPoolExecutor's javadocからの引用は、私が

このクラスはThreadPoolExecutorから継承しながら

を推測することを説明し、継承されたチューニング方法のいくつかは、それのために有用ではありません。特に、corePoolSizeスレッドと無制限キューを使用する固定サイズのプールとして機能するため、maximumPoolSizeの調整は有効な効果を持ちません。さらに、corePoolSizeをゼロに設定するか、allowCoreThreadTimeOutを使用することは、決して良いアイデアではありません。これは、スレッドなしでプールを残して実行可能になったタスクを処理できるためです。

あなたが見逃している重要な部分は、ScheduledThreadPoolExecutorのクラスは「corePoolSizeスレッドおよびアンバウンド形式のキューを使用して、固定サイズのプール」であるということです。したがって、よりcorePoolSize以上の余分なスレッドは生成されません。

corePoolSize == 0で実際に実行される理由がわからない場合は、ThreadPoolExecutorのコードスニペットがあります。少なくとも1つのスレッドが存在することを保証します。

call order: 
1. java.util.concurrent.ScheduledThreadPoolExecutor#scheduleAtFixedRate 
2. java.util.concurrent.ScheduledThreadPoolExecutor#delayedExecute 
3. java.util.concurrent.ThreadPoolExecutor#ensurePrestart 
      /** 
      * Same as prestartCoreThread except arranges that at least one 
      * thread is started even if corePoolSize is 0. 
      */ 
      void ensurePrestart() { 
       int wc = workerCountOf(ctl.get()); 
       if (wc < corePoolSize) 
        addWorker(null, true); 
       else if (wc == 0) //here's your case 
        addWorker(null, false); 
      } 
関連する問題