13

Spring MVCアプリを使用しています。次に実行しようとしているのは、アプリからバックグラウンドタスクを開始または送信することです。

基本的には、ユーザーがアプリで何か他のことをすることにした場合でも、タスクが完了するまでタスクを続行したいと思います。

ただし、必要に応じてタスクを停止/強制終了/一時停止したいと思います。私はこれを行うための良い/より良い方法を探す前にこれを行ったことがないので。

私はこれらが有用であることがわかりました:

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

Javaでどのようにスレッドを強制終了しますか?

Javaスレッド:同じJVMで実行されている別のJavaプログラムから特定のスレッドを表示/一時停止/強制終了することは可能ですか?

それで、@ 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(); }
}

テスト用のコントローラー:

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

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

にアクセスする/job/startと、複数のタスクを同時に実行することはできません。もう1つは、最初の1つが完了した後にのみ実行を開始します

また、私が訪問したとき/job/stop、プロセスは停止していませんが、ここで何が欠けていますか?

4

1 に答える 1

11

スレッドIDの使用は低レベルであり、脆弱です。@Async注釈を使用することにした場合(適切な選択)Future<T>、タスクの実行を制御するために使用できます。Future<T>基本的に、メソッドは次の代わりにを返す必要がありますvoid

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

cancel()これで、それを実行するか、完了するのをFuture待つことができます。

@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オブジェクトを何らかの方法で保存して、後続のリクエストで使用できるようにすることです。もちろん、フィールドやを使用することはできませんThreadLocalFutureセッションに入れることはできますが、シリアル化できず、クラスター間で機能しないことに注意してください。

通常はスレッドプールに支えられているため@Async、タスクが開始されていない可能性があります。キャンセルすると、プールから削除されます。タスクがすでに実行されている場合は、isInterrupted()スレッドフラグまたはハンドルを使用して呼び出しInterruptedExceptionを検出できcancel()ます。

于 2012-10-01T09:37:53.630 に答える