web-dev-qa-db-ja.com

spring @Scheduledアノテーション付きメソッドは異なるスレッドで実行されますか?

@Scheduled(fixedDelay = 10000)アノテーションが付けられたいくつかのメソッドがあります。

アプリケーションのコンテキストでは、この注釈駆動型のセットアップがあります。

<task:annotation-driven />

問題は、場合によってはメソッドの実行の一部が数秒、さらには数分遅れることです。

メソッドの実行が完了するまでに時間がかかっても、他のメソッドは実行されると想定しています。だから私は遅れを理解していません。

多分遅延を減らすか、削除する方法はありますか?

55
froi

スケジューリングに関するドキュメント の意味:

Pool-size属性を指定しない場合、デフォルトのスレッドプールには単一のスレッドしかありません。

したがって、多くのスケジュールされたタスクがある場合は、ドキュメントで説明されているように、より多くのスレッドを持つプールを持つようにスケジューラを構成し、1つの長いタスクが他のすべてのタスクを遅らせないようにする必要があります。

44
JB Nizet

完全を期すために、以下のコードはJava configでスケジューラを設定する最も簡単な方法を示しています。

@Configuration
@EnableScheduling
public class SpringConfiguration {

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

さらに制御したい場合は、@ConfigurationクラスはSchedulingConfigurerを実装できます。

49
G. Demecki

@Scheduledアノテーションが付けられたメソッドは、ある時点で別のスレッドで個別に実行されることを意図しています。

設定でTaskSchedulerを指定していない場合、Springは

Executors.newSingleThreadScheduledExecutor();

単一のスレッドで実行されるScheduledExecutorServiceを返します。そのため、複数の@Scheduledメソッドがある場合、それらはスケジュールされていますが、それぞれスレッドが前のタスクの実行を完了するのを待つ必要があります。キューが空になるよりも早くいっぱいになると、遅延が大きくなり続ける可能性があります。

適切な量​​のスレッドでスケジューリング環境を構成してください。

22

使用できます:

@Bean()
public  ThreadPoolTaskScheduler  taskScheduler(){
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(2);
    return  taskScheduler;
}
7
sj8515465

@ EnableScheduling アノテーションは、重要な情報とその解決方法を提供します。

デフォルトでは、関連するスケジューラ定義を検索します。コンテキスト内の一意のTaskScheduler Bean、またはそれ以外の場合は「taskScheduler」という名前のTaskScheduler Bean。 ScheduledExecutorService Beanに対しても同じルックアップが実行されます。 2つとも解決できない場合、ローカルのシングルスレッドのデフォルトスケジューラが作成され、レジストラ内で使用されます

さらに制御が必要な場合、@ ConfigurationクラスでSchedulingConfigurerを実装できます。これにより、基になるScheduledTaskRegistrarインスタンスにアクセスできます。たとえば、次の例は、スケジュールされたタスクの実行に使用されるエグゼキューターをカスタマイズする方法を示しています。

 @Configuration
 @EnableScheduling
 public class AppConfig implements SchedulingConfigurer {

     @Override
     public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
         taskRegistrar.setScheduler(taskExecutor());
     }

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

(強調を追加)

1
jgreen

スケジュールタスクに単一のスレッドを使用するデフォルトのスプリング。クラスの@Configurationを使用してSchedulingConfigurerを実装できます。参照:https://crmepham.github.io/spring-boot-multi-thread-scheduling/

0
zhaoyou