2013-09-28 23 views
5

için desen iptal uzun koşuyoruz yöntemini iptal etmek hafif desen var mı değiştirir: Hafif, hangi böyle bir kod uzun süren yöntem Java

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

ben, bir Görev sınıf yapmak göreve adımları bölmek biliyor nesneler, bir kuyruk yapmak ve sush durum için herhangi bir basit kod yapısı desen var sadece görevleriniz iptal denetimi ile döngü içinde adımlarla adım, ama merak ettim.

cevap

4

Böyle bir mekanizmanın farkında değilim. Bu mantığı daha da geliştirmek istiyorsanız, rollbackWork()'u gerçekleştirebilmek için çalışmanızı izlemeniz gerektiğinden, iyi tasarlanmış bir nesne yönelimli çözüm en iyi seçim! Tipik olarak, böyle bir senaryo hala oldukça hafif bulmak command pattern kullanılarak uygulanabilir:

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

bir zamanlayıcı veya kuyruk sonra ve sırayla onları geri yuvarlanan böyle bir görev/komut uygulamaları yürütme bakabilirim.

+2

+1 GoF komut desen –

+0

nedeniyle yeterince süre için kabul eder. Ancak gerçek cevap, "Hayır, bunun için basit bir kod yapısı yoktur". Sizin çözümünüz çok küçük bir süreç için biraz ağırdır (“görev nesnelerine adımların altını çizdim” dediğim gibi), ama bunun iplik çıkıntılarını/iplik kesintilerini içeren çok daha iyi bir uygulama olduğunu düşünüyorum. –

+0

@killer_PL: Evet, iş parçacığı kullanmak işi aşırı zorlaştırabilir ... –

1

Adımlar, InterruptedException'u attıran yöntemleri çağırırsa, Thread.interrupt()'u kullanabilirsiniz. Geri alma işlemini gerektiği gibi yapmak için yeterli durum bilgisine sahip olmanız gerekir. adımlar bu şekilde kesintiye edilemiyorsa

yapmanız gerekir doğası gereği güvensiz olduğu için kaldırılmış Thread.stop() mekanizması güvenerek düşünmüyoruz.

Her iki yöntemde de, tam olarak anlattığınız şeyi yapmanın mantıklı olduğu görülmektedir: bu iş akışı mantığını, hesaplama adımlarından bağımsız olarak bir sınıfta kapsüllemek. İptal ve/veya kesintiyi desteklemeli ve yürütülecek bir dizi görevi kabul etmelidir. Bir hesaplama yapmak için ve bir geri rulo: görevleri en az iki yöntem sağlamalıdır akışı beslenmek üzere dikkat edin.

0

java.util.concurrent paketini kullanmayı düşünebilirsiniz. Çalışma adımlarınızı Callables (veya Runnables) olarak sarmanız gerekir.

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!"); 
    } 
} 

Şu anda yürütülen iş parçacığında shutdownNow() 'un interrupt() işlevini çağırabileceğini unutmayın. olmayan interruptible kod yürütülmesine bitmeden shutdownNow() döndürdüğü için za ayr geri alma() senkronize etmek gerekir.

+0

'new Thread (...). Run()'? – assylias

2

Bu düzenleme nasıl yapılır? İstisnalar çok ucuz, bu yüzden hızlı olmalı.

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); 
    } 
} 
İlgili konular