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(),因此如果您想进一步发展此逻辑,那么设计良好的面向对象解决方案是您的最佳选择!通常,这样的场景可以使用命令模式来实现,我仍然觉得它非常轻量级:

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

然后调度程序或队列可以负责执行此类任务/命令实现,并按顺序回滚它们。

于 2013-09-28T08:57:36.103 回答
2

这个编辑怎么样,不是模式吗?例外非常便宜,所以应该很快。

public void caller(){
    try{
        longComputations();
    } catch (MeaningfulRuntimeException e){
        rollbackWork(e.getStep());
    }
}

public void longComputations() {
   ... first step...
   checkStatus(1);

   ... second step...
   checkStatus(2);

   ... third step...
   checkStatus(3);
}

public void checkStatus(int step){
    if ( cancelled ) {
        ... we may rollback here or throw an exception ...
        throw MeaningfulRuntimeException(step);
    }
}
于 2013-09-28T21:20:34.030 回答
1

如果步骤调用抛出的方法,InterruptedException那么您可以使用Thread.interrupt(). 您仍然需要维护足够的状态信息才能正确进行回滚。

如果不能以这种方式中断这些步骤,则不应考虑依赖已弃用的Thread.stop()机制,因为它本质上是不安全的。

似乎无论哪种方式都可以完全按照您的描述进行:将此工作流逻辑封装在一个独立于计算步骤的类中。它应该支持取消和/或中断,并接受一堆要执行的任务。请注意,要输入工作流的任务应至少提供两种方法:一种用于执行计算,另一种用于回滚。

于 2013-09-28T09:02:44.693 回答
0

您可能需要考虑使用 java.util.concurrent 包。您需要将工作步骤包装为 Callables(或 Runnables)。

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()。您可能还需要同步您的 rollback(),因为 shutdownNow() 在不可中断代码完成执行之前返回。

于 2013-09-28T10:48:40.000 回答