Java的轻量级长时间运行方法取消模式

时间:2013-09-28 08:45:05

标签: java multithreading concurrency

是否有一个轻量级模式来取消长期运行方法,取而代之的是这样的代码:

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

我知道我可以创建一个Task类,将步骤细分为任务对象,创建一个队列,然后在循环中逐步执行取消检查,但我只是想知道是否有任何简单的代码结构模式sush情况。

4 个答案:

答案 0 :(得分:4)

我不知道这样的机制。由于您必须跟踪您的工作以便能够执行rollbackWork(),所以如果您想进一步发展这种逻辑,那么精心设计的面向对象解决方案无论如何都是您的最佳选择!通常,这样的场景可以使用command pattern来实现,我仍然觉得它非常轻量级:

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

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

答案 1 :(得分: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);
    }
}

答案 2 :(得分:1)

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

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

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

答案 3 :(得分: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()在不可中断代码完成执行之前返回。