2012-10-01 9 views
10

私は春のMVCアプリケーションを使用しています。次に実行しようとしていることは、自分のアプリケーションからバックグラウンドタスクを開始または送信することです。spring mvcアプリケーションからのバックグラウンドタスクの送信

基本的には、ユーザーがアプリで何か他のことをすることを決断したとしても、タスクが完了するまでその作業を続けていきたいと思います。

しかし、私は必要に応じてタスクを停止/停止/一時停止したいと思います。私はこれをやったことがないので、これを行う良い/良い方法を探しています。

私はこれらが有用であることが判明:

http://blog.springsource.com/2010/01/05/task-scheduling-simplifications-in-spring-3-0/

How do you kill a thread in Java?

Java threads: Is it possible view/pause/kill a particular thread from a different java program running on the same JVM?

だから私は私のバックグラウンドタスクを提出する@Asyncタスクを使用していたが、スレッドを使用していましたそれを後で入手し、必要に応じて停止させるためのIDですか?

これは正しいアプローチですか?私はマルチスレッドの経験がないので、私はここに来て聞いています。

コードの更新:

public interface Worker { 
    public void work(); 
    public void cancel(); 
} 

実装:

@Component("asyncWorker") 
public class AsyncWorker implements Worker { 

    @Async 
    public void work() { 
     String threadName = Thread.currentThread().getName(); 
     System.out.println(" " + threadName + " beginning work"); 
     try { 
       Thread.sleep(10000); // simulates work 
     } catch (InterruptedException e) { 
      System.out.println("I stopped"); 
     } 
     System.out.println(" " + threadName + " completed work"); 
    } 

    public void cancel() { Thread.currentThread().interrupt(); } 
} 

コントローラテスト目的のために:私は/job/startにアクセスすると

@ResponseBody 
@RequestMapping("/job/start") 
public String start() { 
    asyncWorker.work(); 
    return "start"; 
} 

@ResponseBody 
@RequestMapping("/job/stop") 
public String stop() { 
    asyncWorker.cancel(); 
    return "stop"; 
} 

、私は1つ以上を実行することはできませんタスクを同時に実行する。もう1つは、最初に完了した後に実行を開始します

/job/stopにアクセスしたときにプロセスが停止していない場合、私はここで何が欠けていますか?

答えて

9

スレッドIDの使用が低すぎると脆弱です。 @Async annotation(良い選択)を使用することを決めた場合は、Future<T>を使用してタスクの実行を制御できます。基本的にあなたの方法ではなくvoidFuture<T>を返す必要があります:

@Async 
public Future<Work> work() //... 

今、あなたはFutureか、それが完了するのを待つことcancel()ことができます。

@ResponseBody 
@RequestMapping("/job/start") 
public String start() { 
    Future<Work> future = asyncWorker.work(); 
    //store future somewhere 
    return "start"; 
} 

@ResponseBody 
@RequestMapping("/job/stop") 
public String stop() { 
    future.cancel(); 
    return "stop"; 
} 

トリッキーな部分はそう何とか返さfutureオブジェクトを格納することです後続の要求に使用できます。もちろん、フィールドやThreadLocalは使用できません。ただし、セッションに入れることができますが、Futureはシリアル化可能ではなく、クラスタ間では動作しません。

通常、@Asyncはスレッドプールによってバックアップされているため、タスクが開始されていない可能性もあります。キャンセルすると、プールから削除されます。タスクが既に実行されている場合はisInterrupted()スレッドフラグを使用するか、InterruptedExceptionを処理してcancel()コールを検出します。

+0

+1の@Async。 http:// staticへのリンクを追加できますか?springsource.org/spring/docs/3.0.x/reference/scheduling.html? –

+0

@Tomasz Nurkiewiczよろしくお願いします。 'fooAsync()'の実装を実際に含むクラスは、Runnableを実装する必要がありますか?バックグラウンドタスクを実行しているスレッドを中断するcancelメソッドを作成した場合、Thread.currentThread()。interruptはその特定のスレッドを中断しますか?あなたは例を挙げてもらえますか? –

+0

@DavidGrant:確かに、あなたもSO上の投稿を自由に編集することができます。 –

関連する問題