2010-07-05 40 views
5

我有一個方法,它在概念上,看起來像:怎麼寫中斷的方法

Object f(Object o1) { 
    Object o2 = longProcess1(o1); 
    Object o3 = longProcess2(o2); 
    return longProcess3(o3); 
} 

凡過程本身也可能是化合物

Object longProcess1(Object o1) { 
    Object o2 = longSubProcess1(o1); 
    return longSubProcess2(o2); 
} 

如此反覆,用不同進程可能坐在不同的模塊中。大多數過程很長,因爲它們在計算上很昂貴,而不是IO限制。

到目前爲止好,但現在我想f作爲一個整體是可以打斷的。 The recommended Java way to do that將定期檢查中斷標誌Thread.interrupted()。這是非常簡單的,但如果我需要改變我的方法,像它可以迅速成爲累贅:現在

Object f(Object o1) { 
    Object o2 = longProcess1(o1); 
    if (Thread.interrupted()) throw new InterruptedException(); 
    Object o3 = longProcess2(o2); 
    if (Thread.interrupted()) throw new InterruptedException(); 
    return longProcess3(o3); 
} 

Object longProcess1(Object o1) { 
    Object o2 = longSubProcess1(o1); 
    if (Thread.interrupted()) throw new InterruptedException(); 
    return longSubProcess2(o2); 
} 

... 

我明白了合理的那樣工作 - 它可以讓我更好的控制時, InterruptedException(例如)將拋出,避免將對象留在不一致的狀態 - 但我很想知道是否有更好的方法來做這個*。 *在Java中,不是AspectJ,我認爲這是非常合適的,但我堅持使用Java。

+0

我會擔心與包含REF對方線程代碼死鎖。 – 2010-07-05 11:13:39

回答

7

你可以使用一個接口和一個動態代理:

public class Wrapper { 
    public static <T> T wrap(Class<T> intf, final T impl) { 
     ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
     Object proxy = Proxy.newProxyInstance(cl, new Class<?>[] {intf}, 
       new InvocationHandler() { 
      public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable { 
       if (Thread.interrupted()) { 
        throw new InterruptedException(); 
       } 
       return method.invoke(impl, args); 
      } 
     }); 
     return intf.cast(proxy); 
    } 
} 

interface Processes { 
    Object longProcess1(Object o); 
    ... 
} 

public class ProcessesImpl implement Processes { 
    Processes self = Wrapper.wrap(Processes.class, this); 

    public Object f(Object o1) { 
     Object o2 = self.longProcess1(o1); 
     Object o3 = self.longProcess2(o2); 
     return self.longProcess3(o3); 
    } 

    public Object longProcess1(Object o1) { 
     Object o2 = self.longSubProcess1(o1); 
     return self.longSubProcess2(o2); 
    } 

    .... 
} 
+0

有趣,但仍然有點麻煩。我需要爲所有相關的類添加一個字段,並限定許多方法調用。由此產生的方法*更優雅,但我會給你的! – Oak 2010-07-05 12:19:10

0

難道我得到這個權利,你按順序運行的方法是在同一嵌套級別?如果是這樣,爲什麼不實施你的計算方法爲java.lang.Runnable實例,將它們組織成列表並在循環中啓動它們?然後,您只有一個地方使用Thread.interrupted()檢查。

您可能會考慮使用java.util.concurrent.ExecutorService來幫助控制計算任務。

更新了一個例子:

import java.util.ArrayList; 
import java.util.List; 

public class Test { 

    public static void main(String[] args) { 
     List<CompoundProcess> subProcesses1 = new ArrayList<CompoundProcess>(); 
     subProcesses1.add(new CompoundProcess() { 
      public void run() { 
       System.out.println("Process 1.1"); 
      } 
     }); 
     subProcesses1.add(new CompoundProcess() { 
      public void run() { 
       System.out.println("Process 1.2"); 
      } 
     }); 

     List<CompoundProcess> subProcesses2 = new ArrayList<CompoundProcess>(); 
     subProcesses2.add(new CompoundProcess() { 
      public void run() { 
       System.out.println("Process 2.1"); 
      } 
     }); 
     subProcesses2.add(new CompoundProcess() { 
      public void run() { 
       System.out.println("Process 2.2"); 
      } 
     }); 

     List<CompoundProcess> processes1 = new ArrayList<CompoundProcess>() {}; 
     processes1.add(new CompoundProcess(subProcesses1)); 
     processes1.add(new CompoundProcess(subProcesses2)); 

     CompoundProcess process = new CompoundProcess(processes1); 
     process.run(); 
    } 


    static class CompoundProcess implements Runnable { 

     private List<CompoundProcess> processes = new ArrayList<CompoundProcess>(); 

     public CompoundProcess() { 
     } 

     public CompoundProcess(List<CompoundProcess> processes) { 
      this.processes = processes; 
     } 

     public void run() { 
      for (Runnable process : processes) { 
       if (Thread.interrupted()) { 
        throw new RuntimeException("The processing was interrupted"); 
       } else { 
        process.run(); 
       } 
      } 
     } 
    } 

} 
+0

不,這些過程在許多不同的地方 - 我試圖通過展示'longProcess1'本身就是複合的,可能我還不夠清楚 - 所以我編輯了這個問題來澄清。 – Oak 2010-07-05 11:52:44

+0

一旦相同級別的進程順序運行,它們在不同的地方啓動並不重要。我用一個例子更新了我的答案。你可以將進程嵌套到你想要的級別。 – fnt 2010-07-05 12:39:44