2016-10-29 14 views
1

Spring Webアプリケーション内には5分ごとに呼び出される予定のタスクがあります。@スケジュールされたタスクが終了する方法を教えてください。

@Scheduled(fixedDelay = 300000) 
    public void importDataTask() 
{ 
    importData(); //db calls, file manipulations, etc.. 
} 

通常のタスクは、日のためにスムーズに実行されますが、時々、例の方法importaData()が終了しないので、importDataTask()が再び呼び出されることはありません、私は、アプリケーションを再起動するまで、すべてがブロックされることが起こります。

質問は、メソッドが無期限にブロックされないようにするための実現可能なメソッドがあるかどうか(リソースを待っているかどうかなど)?

+0

デッドロックが見つかった方が良い方法ですが、どこが襲っているのかわかりません。私たちが修正案を提案できるかどうかは疑問です。 –

答えて

1

質問です:メソッド は無期限(waybeリソースを待っている、または他の 何かを)ブロックされないことを確認するためにfeasibile方法はありますか?

スケジューリングを正確な定期的な間隔で計画することができない場合は、固定遅延を使用せず、遅延+最終実行の2つの条件を使用する必要があります。
2つの条件が満たされているかどうかをチェックするタスクをスケジューリングし、その場合は重要な処理を実行できます。そうでなければ、次のスケジュールを待つ。
このようにして、ブロックしないでください。タスクが固定遅延を超過すると、しばらく待つことができます。固定遅延が頻繁に超過するため問題がある場合は、おそらく固定遅延を使用しないでください。そうでない場合は、それを敏感に増やしてください。ここで

例(編集せずに書いて申し訳ありませんが間違いであれば。):

private boolean isLastImportDataTaskFinished; 

@Scheduled(fixedDelay = 300000) 
public void importDataTaskManager(){ 
    if (isLastImportDataTaskFinished()){ 
     new Thread(new ImportantDataProcessing())).start();   
    } 
    else{ 
     // log the problem if you want 
    } 
} 

private isLastImportDataTaskFinished(){ 
    // to retrieve this information, you can do as you want : use a variable 
    // in this class or a data in database,file... 
    // here a simple implementation 
    return isLastImportDataTaskFinished; 
} 

のRunnableクラス:

public class ImportantDataProcessing implements Runnable{ 
    public void run(){  
     importData(); //db calls, file manipulations, etc..  
    } 
} 

コメント:

しかし、私は実行する場合それはスレッドとして私がそれを超えるとそれを見つける場合、私はそれを殺すことができます 私はそれを参照していないので、時間制限は( の考えでは、第2のタスクを使用してスタック状態を判断しています)?

ExecutorService(ここでは質問があります:How to timeout a thread)を使用できます。ここで

非常に単純な例:

ExecutorService executor = Executors.newSingleThreadExecutor(); 
Future future = executor.submit(new ImportantDataProcessing()); 
try { 
    future.get(100, TimeUnit.SECONDS); 
} 
catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
catch (ExecutionException e) { 
    e.printStackTrace(); 
} 
catch (TimeoutException e) { 
    // the timeout to handle but other exceptions should be handled :) 
    e.printStackTrace(); 
} 
executor.shutdown(); 

興味深い情報がImportantDataProcessing処理によって返されることがあります場合は、あなたが将来を入力するタスクの代わりに、実行可能なインスタンスを使用することができます。

+0

ありがとう@davidxxx、私は疑いがある。メソッドimportData()が何らかの理由でブロックされている場合、fixedDelayは前のバッチの終了を待つので、importDataTask()の次の反復は呼び出されません。最後のインポート日をログに記録するというアイデアは、このように(DBから)この値をチェックするためだけの2番目のタスクを持つことができます。しかしその後?たぶん私はスレッドの機能を調べるべきでしょう。 – frankieta

+1

確かに。これを避けるには、新しいスレッドでimportData()を実行します。このようにして、importDataTaskManager()はブロックされません。私は私の答えを更新:)しかし、importData()が決して終了しない場合、問題ははるかに深刻です。 2番目のタスクを使用することも考えられます。 – davidxxx

+0

私は間違いなくそれを試してみます。インポートするデータは膨大なものになる可能性があるため、スケジュールされたタスクが実行されるたびに、データをチャンクで分割して一度にインポートすると思います。しかし、もし私がそれを参照していないので、時間制限を超えていることがわかったら、私はそれをスレッドとして実行します(2番目のタスクを使用してスタック状態を判断するという考え方で)?申し訳ありませんが、私は元の質問のために遠慮しています。 – frankieta

0

まず、確かに。あなたのコードに埋め込まれているログ/メッセージ/電子メールなど、プロセスがブロックされている場合にあなたに思い出させる多くの実現可能な方法があります。

第2に、ブロックしたいかどうかによって決まります。あなたが意図していない場合は、新しいスレッドやタイムアウトを選択することができます。

+0

はい、ブロックは私の意図ではありません。限られた時間間隔(5分)は、ユーザがインポートの結果を半リアルタイムで見ることを望むためです。 – frankieta

関連する問題