5

次のようなコードを置き換える、長時間実行されるメソッドをキャンセルする軽量のパターンはありますか:

public void longComputations() {
   ... first step...
   if ( cancelled ) {
      rollbackWork();
      return;
   }
   ... second step...
   if ( cancelled ) {
      rollbackWork();
      return;
   }
   ... third step...
   if ( cancelled ) {
      rollbackWork();
      return;
  }
}

Task クラスを作成し、ステップをタスク オブジェクトに分割し、キューを作成し、キャンセル チェックを使用してループ内でタスクをステップごとに実行できることはわかっていますが、そのような状況のための簡単なコード構造パターンがあるのではないかと思っています。

4

4 に答える 4

4

私はそのようなメカニズムを認識していません。を実行できるようにするために作業を追跡する必要があるためrollbackWork()、このロジックをさらに進化させたい場合は、適切に設計されたオブジェクト指向ソリューションが最善の選択です。通常、このようなシナリオはコマンド patternを使用して実装できますが、それでも非常に軽量です。

// Task or Command
public interface Command {
    void redo();
    void undo();
}

スケジューラまたはキューは、そのようなタスク/コマンドの実装を実行し、それらを順番にロールバックすることができます。

于 2013-09-28T08:57:36.103 に答える
0

java.util.concurrent パッケージの使用を検討してください。作業ステップを Callable (または Runnable) としてラップする必要があります。

public class InterruptibleTest {
    public static void main(String[] args) { try {
        final ExecutorService queue = Executors.newFixedThreadPool(1);
        queue.submit(new Callable<Void>() { @Override public Void call() { busyWait(1000); return null; } });
        queue.submit(new Callable<Void>() { @Override public Void call() { busyWait(1000); return null; } });
        queue.submit(new Callable<Void>() { @Override public Void call() { busyWait(1000); return null; } });
        final AtomicBoolean cancelled = new AtomicBoolean();
        new Thread() { @Override public void run() {
                try { Thread.sleep(1500); } catch (InterruptedException ex) { }
                queue.shutdownNow();
                cancelled.set(true);
            }
        }.run();
        if (cancelled.get()) { rollback(); }
        queue.shutdown();
        System.out.println("Finished");
    } catch (Exception ex) { ex.printStackTrace(System.err); } }

    public synchronized static void busyWait(int millis) {
        System.out.println("Start");
        long until = System.currentTimeMillis() + millis;
        while (System.currentTimeMillis() < until) { }
        System.out.println("Stopped");
    }
    public synchronized static void rollback() {
        System.out.println("Rollback!");
    }
}

shutdownNow() は、現在実行中の作業スレッドで interrupt() を呼び出す場合があることに注意してください。割り込み不可能なコードの実行が終了する前に shutdownNow() が戻るため、おそらく rollback() も同期する必要があります。

于 2013-09-28T10:48:40.000 に答える