是否有一个轻量级模式来取消长期运行方法,取而代之的是这样的代码:
public void longComputations() {
... first step...
if ( cancelled ) {
rollbackWork();
return;
}
... second step...
if ( cancelled ) {
rollbackWork();
return;
}
... third step...
if ( cancelled ) {
rollbackWork();
return;
}
}
我知道我可以创建一个Task类,将步骤细分为任务对象,创建一个队列,然后在循环中逐步执行取消检查,但我只是想知道是否有任何简单的代码结构模式sush情况。
答案 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()在不可中断代码完成执行之前返回。