私は私のプロジェクトの3つの方法は、そのうちの一つのcron式と他の2つの固定されている遅延され、@Scheduledで注釈を付けています。注釈は、次のようになります。
方法1:
@Scheduled(fixedDelay = 20000)
@Async
protected void checkBrokenEngines() {
方法2:
@Scheduled(fixedRate = 20000)
@Async
public void checkAvailableTasks() throws Exception {
方法3:
@Scheduled(cron = "0 0 2 * * ?")
protected void deleteOldData() {
以前私は、という問題だったcheckBrokenEngines
とcheckAvailableTasks
方法は、以前の1が終了するまで次の実行が実現しなかった、実行されようと遅かったが。ドキュメントとここにStackOverflowからいくつかのトピックを読んで、私は私のプロジェクトがいくつか間違っていたことを見たプールサイズの設定をし、メソッドがで注釈されていなかった非同期。(非同期は、古いものは終わっていない場合でも、これは私のアプリケーションで問題が発生することはありませんので、次回起動実行のためでした)
今、別の問題は私の質問である、来ています:
ときにdeleteOldData()
メソッドが実行され、それが終了するまで、他の2つの方法のどちらが実行されます。この方法は、他の2つの実行をブロックしたことを見た後、私はこの方法を実行する時間がかかり、他の2つは必ず規定時間内に正確に呼び出された場合でも、非同期としてその後方法を注釈付き。どうして?私の理解では、これらのメソッドは非同期で指摘されているので、これは起こるべきではありませんし、プールはそれらを実行するための十分なスペースがあります。
PS:deleteOldData()
非同期にすることはできません。これは、前の実行が完了した直後に開始する必要があります。
EDIT 1:
非同期エグゼキュータ設定:
@Override
public AsyncTaskExecutor getAsyncExecutor() {
log.debug("Creating Async Task Executor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(10000);
return new ExceptionHandlingAsyncTaskExecutor(executor);
}
すべての @Scheduled
マークの呼び出しは、スケジュールタスク(非同期またはそれ以外)にデフォルトの単一スレッドのexecutorを使用します。
すべての@Async
タスクは、AOPインターセプターと実行のために異なるaysncスレッドプールエグゼキュータに渡されています。
私はあなたの混乱を返すメソッド非同期(async)という事実から来ていると思いますすぐに deleteOldDataが実行されたときにだけ、1つのスレッドをブロックし、他のスケジュールされたタスクの実行があるとして、それは同期実行されています。
あなたは、彼らが次々に予定されているスケジュールされたタスクのデフォルトスレッドプール(シングルスレッド)を持っているので。
他の方法は、彼らはそれが終わるかなくても実行@Asyncでアノテート。いくつかのケースでは、私は同時に実行する2つのメソッドを持っています。deleteOldDataが実行されているときには、非同期メソッドは、それが終了するまで実行することを停止します。この私が理解していないよ何、申し訳ありません:/ -
これは、スケジューリングと異なっている - あなたの非同期executorが遊びに来て、彼らは同時に実行されている場所です。
次のいずれかの方法でこの問題を解決することができます:
あなたは使用することができspring.task.scheduling.pool.size=10
、タスクスケジューラのプールサイズを設定するには、アプリケーションのプロパティで。
また、異なるタスクスケジューラを使用します。デフォルトのスケジューラを使用してください@Scheduled
(予定注釈を削除する)非同期タスクについては、以下のようなタスクとのconfigure何か
タスクスケジューラを渡すように要求された機能拡張があり@Scheduled
、その後、手動でスケジュールタスクになるまで、注釈が。
非同期呼び出しのための新しいタスクスケジューラを登録し、ポスト構造の段階でメソッドをスケジュールします。何かのようなもの
コンフィギュレーション
@Bean("asyncTaskScheduler")
public TaskScheduler asyncTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
サービス
@Autowired
private TaskScheduler asyncTaskScheduler;
@PostConstruct
void schedule() {
asyncTaskScheduler.scheduleAtFixedRate(this::checkAvailableTasks, 20000L);
asyncTaskScheduler.scheduleAtFixedDelay(this::checkBrokenEngines, 20000L);
}
@Async
public void checkBrokenEngines() {...}
@Async
public void checkAvailableTasks() throws Exception {...}