0

@Scheduled(fixedRate = 10000)でメソッドを実行する@Scheduling使用し、私はのThread.sleep又はロックは、他のスレッドを使用した場合SchedulingConfigurerスプリングのJava @Scheduling構成

@Bean(destroyMethod="shutdown") 
    public Executor taskExecutor() { 
     return Executors.newScheduledThreadPool(10); 
    } 

を実装することによってスレッドを@Scheduling設定Thread.sleepウェイクアップまたはロックが解除されない限り、Executorによって作成されます。

私は10のプールのサイズがある場合、10人のスレッドが10000ミリ秒のレートで作成されるはずです。

答えて

0

基本的に、このような行動は、スプリングによって内部的に使用されScheduledExecutorService実装から来ています。あなたはこのコードを実行する場合は、同じ動作をわかります。

public static void main(String[] args) throws Exception { 
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(10); 
    executor.schedule(() -> { 
     System.out.println("Running task in thread " + Thread.currentThread().getId()); 
     try { 
      Thread.sleep(Integer.MAX_VALUE); 
     } catch (InterruptedException e) { 
      System.out.println("interrupted while sleeping"); 
     } 
    }, 1000, TimeUnit.MILLISECONDS); 
    Thread.sleep(10000); 
    executor.shutdownNow(); 
} 

スケジュールスレッドプールにタスクを送信すると、それがdelayedExecuteメソッドに渡されRunnableScheduledFutureに包まれています。このメソッドは、タスクをキューに追加し、現在のワーカー数がcorePoolSize未満の場合は新しいワーカーを開始します。ワーカーは、キューからタスクを取得し、それを処理してrunメソッドを呼び出そうとします。実行の準備ができている場合にのみタスクを返す専用のDelayedWorkQueue実装があります。 reExecutePeriodicはほぼ同じである(あなたはそれがrunAndResetで実際のタスク・ロジックを呼び出す見ることができるように、

/** 
    * Overrides FutureTask version so as to reset/requeue if periodic. 
    */ 
    public void run() { 
     boolean periodic = isPeriodic(); 
     if (!canRunInCurrentRunState(periodic)) 
      cancel(false); 
     else if (!periodic) 
      ScheduledFutureTask.super.run(); 
     else if (ScheduledFutureTask.super.runAndReset()) { 
      setNextRunTime(); 
      reExecutePeriodic(outerTask); 
     } 
    } 

次の実行時間を計算し、再びキューに同じ更新タスクを送信します。ここRunnableScheduledFuturerun方法がどのように見えるかですschedule)。直前の実行が終了してから更新された時間に何度も再実行されるすべての実行に対して1つの定期的なタスクしかありません。したがって、そのようなスレッドプールは、任意の瞬間に各タスクタイプの単一のインスタンスのみを実行し、異なるタイプのタスクに対してのみスケーリングします。

春スケジュールのタスクが興味深い場合は、ScheduledTaskRegistrarクラス、特にscheduleFixedDelayTaskメソッドを参照してください。

0

スレッドプールを使用する場合: デフォルトでは、プールには10個のスレッドがあります(既に初期化されています)。 @scheduledが初めて実行されたとき、この関数はプールからのスレッド(現在は残りの9つのスレッド)で実行されます。まだ終了した関数と@scheduledが再度実行されると、関数はあなたの他のスレッドで実行されますあなたのプール、今あなたはあなたのプールに残っている8スレッドを持っています。 (アイドル8、実行スレッド2)

スレッドプールを使用していない場合は、1つのスレッドのみが使用されます。

春のドキュメント:あなたは「プールサイズ」属性を指定しない場合

、デフォルトのスレッドプール は、単一のスレッドを持つことになります。スケジューラのための他の設定 オプションはありません。

https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/scheduling.html

+0

私が観察したことは、Thread.sleepを使用するか、pool-size 10の@scheduledメソッド内でロックすると、スレッドが1回だけ実行されて永久にロックされるということです。たとえば、1つのスレッドが10のプールからスケジュールされた方法で実行され、1つのスレッドがロックにスタックされた場合、他の9つのスレッドはスケジュールされたメソッドメソッドに対して実行されません。すべてが固まった。たとえ私が睡眠を使ったとしても。 –

+0

あなたのコードと要点を共有できますか?というのは、コードがシングルスレッドを使用しているように見えるからです。 – Makoton

+0

スケジュールアノテーションで@Asyncのみを追加する必要があります。 –

関連する問題