2013-09-28 70 views
5

有一個輕量級的模式,取消長乳寧方法,至極替換代碼:輕型長時間運行的方法取消模式的Java

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

我知道我可以做一個任務類,細分步驟任務對象,建立一個隊列,只是做一步一步循環取消檢查,但我只是想知道是否有任何簡單的代碼結構模式sush情況。

回答

4

我不知道這樣的機制。由於您必須跟蹤您的工作以便能夠執行rollbackWork(),所以無論如何,如果您想進一步發展此邏輯,精心設計的面向對象的解決方案無論如何都是您的最佳選擇!通常情況下,這樣的場景可以使用command pattern,我仍然覺得非常輕便的實現:然後

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

調度或隊列可以採取執行這樣的任務/命令實現的照顧,爲了滾動他們回來的。

+2

+1 GoF指令模式 –

+0

我會接受,因爲有足夠的時間段。但是可以肯定的是,真正的答案是「不,這沒有簡單的代碼結構」。你的解決方案對於非常小的進程有點重量級(正如我所說的細分任務對象的步驟),但我認爲這是一個涉及線程擴展/線程中斷的更好的練習。 –

+0

@killer_PL:是的,使用線程可能會使任務過於複雜...... –

1

如果這些步驟調用拋出InterruptedException的方法,那麼您可以使用Thread.interrupt()。您仍然需要維護足夠的狀態信息才能正確執行回滾。

如果這些步驟不能以這種方式中斷,您應該而不是考慮依靠已棄用的Thread.stop()機制,因爲它本質上是不安全的。

看來,無論採用哪種方式,您都可以完全按照您的描述進行操作:將此工作流邏輯封裝在與計算步驟無關的類中。它應該支持取消和/或中斷,並接受一堆要執行的任務。請注意,要饋送到工作流中的任務應該至少提供兩種方法:一種執行計算,另一種將其回滾。

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()在不可中斷的代碼執行完成之前返回。

+0

'new Thread(...)。run()'? – assylias

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); 
    } 
} 
相關問題