2017-07-18 6 views
3

私は@Scheduledというアノテーションを持つ複数のコンポーネントを持っていますが、同じ時間に実行するようにスケジュールされていても、Springは一度に1つずつしか起動しません。各スレッドスケジューラを独自のスレッドで実行する

私の使用例は次のとおりです。私は各@Scheduledアノテーションを独自のスレッドで実行するが、スレッドごとに1回しか実行しない。タスクスケジューラを実行するようにスケジュールされるよりも長い時間がかかること

@Scheduled(cron = "0 * * * * *") //run every minute 
public void methodA() { 
    log.info("Running method A"); 
    executeLongRunningJob("Finished method A"); 
} 

@Scheduled(cron = "0 * * * * *") //run every minute 
public void methodB() { 
    log.info("Running method B"); 
    executeLongRunningJob("Finished method B");  
} 

private void executeLongRunningJob(String msg) { 
    Thread.sleep(70 seconds); 
    System.out.println(msg); 
} 

注:

は2つのスケジューラと、この擬似コードを考えます。これは非常に重要です。私は、スケジューラの実行が完了する前に再開したくありません。箱から出して、このコードを実行する

は私にこの出力を与える:

Running method A 
Finished method A 
Running method B 
Finished method B 
Running method A 
Finished method A 
Running method B 
Finished method B 
... and so on 

だから、明らかにそのは、シングルスレッドで両方のスケジューラを実行しています。私は高価な方法で@Asyncを置く


新しいスケジューラが開始される前に、高価なメソッドが終了していないことを除いて、その後、私はほとんど、正しい動作を取得。この出力

Running method A 
Running method B 
Running method A 
Running method B 
Finished method A 
Finished method B 
... and so on 

私が希望です:

Running method A 
Running method B 
Finished method A 
Finished method B 
Running method A 
Running method B 
Finished method A 
Finished method B 
... and so on 

どのように私はこれを達成することができますか? 各スケジューラを同時に実行したいが、もう一度実行する前に終了するまで待つ。 私は、複数のスケジューラが同じ時に実行されることがあります。

+0

'' synchronize'とExecutor'は – Ashish

答えて

5

デフォルトですが、スケジューラはサイズが1のスレッドプールを使用しているため、すべてのタスクが順番に処理されています。必要なプールサイズでTaskScheduler beanを構成することでそれを行うことができます。それは、例えば、別のスレッドで、すべてのスケジュールされたタスクを実行します

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.annotation.Bean; 
import org.springframework.scheduling.TaskScheduler; 
import org.springframework.scheduling.annotation.EnableScheduling; 
import org.springframework.scheduling.annotation.Scheduled; 
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 

import java.util.Date; 

@SpringBootApplication 
@EnableScheduling 
public class Application { 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 

    @Bean 
    public TaskScheduler taskScheduler() { 
     final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); 
     scheduler.setPoolSize(10); 
     return scheduler; 
    } 


    @Scheduled(fixedDelay = 2 * 1000L, initialDelay = 3 * 1000L) 
    public void scheduled1() throws InterruptedException { 
     System.out.println(new Date() + " " + Thread.currentThread().getName() + ": scheduled1"); 
     Thread.sleep(1000); 
    } 

    @Scheduled(fixedDelay = 3 * 1000L, initialDelay = 3 * 1000L) 
    public void scheduled2() throws InterruptedException { 
     System.out.println(new Date() + " " + Thread.currentThread().getName() + ": scheduled2"); 
     Thread.sleep(1000); 
    } 
} 

:次の例を考えてみましょう

Tue Jul 18 20:21:50 CEST 2017 taskScheduler-1: scheduled2 
Tue Jul 18 20:21:50 CEST 2017 taskScheduler-2: scheduled1 
Tue Jul 18 20:21:53 CEST 2017 taskScheduler-1: scheduled1 
Tue Jul 18 20:21:54 CEST 2017 taskScheduler-3: scheduled2 
Tue Jul 18 20:21:56 CEST 2017 taskScheduler-2: scheduled1 
Tue Jul 18 20:21:58 CEST 2017 taskScheduler-4: scheduled2 
Tue Jul 18 20:21:59 CEST 2017 taskScheduler-1: scheduled1 
+0

が答えてくれてありがとう役立つかもしれません。一つの質問。この例では、同時に2つのスケジューラしか実行されないことを確認します。だからスケジュール2は、別のスケジュール2が終了するまで開始しませんか? –

+0

私はプールサイズがスケジューラの数と同じサイズであることを確認するだけでいいですか?私はこれを確認し、それは働いた。 –

+0

正しいこと:+1: –

関連する問題