2013-09-28 2 views
5

에 대한 패턴을 취소 긴들이받은 방법을 취소 할 수있는 경량의 패턴이 있습니까 대체 는 경량, 느릅 나무 같은 코드를 장기 실행 방법은 자바

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

이 내가하는 작업 클래스를 만드는 작업에 단계를 나눌 수 있다는 사실을 알고 객체를 만들고, 대기열을 만들고, 취소 확인을 사용하여 루프에서 단계별로 작업을 단계적으로 수행합니다.하지만 나는 그저 단순한 코드 구조 패턴이 있는지 궁금합니다.

답변

4

저는 이러한 메커니즘을 알지 못합니다. rollbackWork()을 수행 할 수 있도록 작업을 추적해야하므로이 논리를 더욱 발전 시키려면 잘 설계된 객체 지향 솔루션이 최선의 선택입니다! 일반적으로 이러한 시나리오는 아직도 꽤 경량 찾아 command pattern를 사용하여 구현 될 수있다 :

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

스케줄러 또는 큐는 순서대로 다시 롤링, 그러한 작업/명령 구현을 실행 돌볼 수 있습니다.

+2

+1 GoF 명령 패턴 –

+0

충분한 기간으로 인해 받아 들일 것입니다. 그러나 실제로 적절한 대답은 "아니오, 단순한 코드 구조가 아닙니다"입니다. 귀하의 솔루션은 약간의 헤비급 (매우 작은 프로세스에 대해'세분 된 작업 개체'라고 말했듯이)이지만, 스레드 exteptions/thread 중단과 관련된 더 나은 방법이라고 생각합니다. –

+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()를 호출 할 수 있습니다. 중단없는 코드가 실행을 끝내기 전에 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); 
    } 
} 
관련 문제