English 中文(简体)
处理处决问题的最佳方式是什么?
原标题:What is the best way to handle an ExecutionException?

我有办法完成一些任务,时间不长。 我利用ExecutorServer.submit()获得未来物体,然后我用时间说出未来。 这是很出色的工作,但我的问题是处理我的任务可以推翻的核查例外的最佳办法。 下面的法典是行之有效的,保留了所核查的例外情况,但是,如果在方法签字改动中列举的经核实的例外情形,这似乎极为模糊,很容易打破。

关于如何确定这一点的任何建议? 我需要针对贾瓦5,但我也很想知道,在更新的 Java版本中是否有很好的解决办法。

public static byte[] doSomethingWithTimeout( int timeout ) throws ProcessExecutionException, InterruptedException, IOException, TimeoutException {

    Callable<byte[]> callable = new Callable<byte[]>() {
        public byte[] call() throws IOException, InterruptedException, ProcessExecutionException {
            //Do some work that could throw one of these exceptions
            return null;
        }
    };

    try {
        ExecutorService service = Executors.newSingleThreadExecutor();
        try {
            Future<byte[]> future = service.submit( callable );
            return future.get( timeout, TimeUnit.MILLISECONDS );
        } finally {
            service.shutdown();
        }
    } catch( Throwable t ) { //Exception handling of nested exceptions is painfully clumsy in Java
        if( t instanceof ExecutionException ) {
            t = t.getCause();
        }
        if( t instanceof ProcessExecutionException ) {
            throw (ProcessExecutionException)t;
        } else if( t instanceof InterruptedException ) {
            throw (InterruptedException)t;
        } else if( t instanceof IOException ) {
            throw (IOException)t;
        } else if( t instanceof TimeoutException ) {
            throw (TimeoutException)t;
        } else if( t instanceof Error ) {
            throw (Error)t;
        } else if( t instanceof RuntimeException) {
            throw (RuntimeException)t;
        } else {
            throw new RuntimeException( t );
        }
    }
}

== UPDATE ==

许多人张贴了建议1的答复,作为一般例外重新增长,或2)作为不受制约的例外重新增长。 我不想做其中任何一个,因为这些例外类型(ProcessExecutionException, InterruptedException, IOException, TimeException)都很重要,它们都将通过处理电话处理。 如果我不需要时间,那么我就想把这四种特定例外类型(除了时间外,还有时间外)。 我并不认为,增加一个时间外观特征应改变我的签名方法,以 throw弃一种通用的例外情况。

最佳回答

我深入探讨这一问题,并说出一点。 Java5、6或7没有简单答案。 除了你指出的cl、ver和脆弱之外,你的解决办法实际上还存在着以下问题:在你称之为<条码>植被()时,你正在停下来的<条码>。

这就是说,你所介绍的法典中所用方法的所有线性信息,都只是从执行中,而不是在nes原因中,这些原因只涵盖从<条码>(<> 起的线。 这就是说,你的<代码>doSomethingWithtimeout方法甚至在你在此所举的例外情况的痕迹中出现。 你们只得从迫害者身上穿孔。 这是因为<条码>ExecutionException是唯一在电话线上创建的(见FutureTask.get()。

我知道的唯一解决办法是复杂的。 很多问题源自于<条码>的自由例外规定——<条码>。 您可界定<代码> 可加附的新变量,其中具体指明了它们提出的哪些例外,例如:

public interface Callable1<T,X extends Exception> extends Callable<T> {

    @Override
    T call() throws X; 
}

这使得可使用的方法能够有更精确的<代码>第>条码条款。 如果你想要支持签字,但以N为例外,你就不需要这一接口的N级变量,不幸的是。

现在,你可以围绕JDK Executor 撰写一份总结材料,该表可加固,并填写一份强化的<代码>Future,例如:guava s 。 核对的例外情况类型在汇编时间时从<代码>Executorservice的生成和类型到<代码>Future/code>s,最后在getChecked方法上公布。

你们如何通过编辑时的类型安全。 这意味着:

Future.get() throws InterruptedException, ExecutionException;

你可以呼吁:

CheckedFuture.getChecked() throws InterruptedException, ProcessExecutionException, IOException

So the unwrapping problem is avoided - your method immediately throws the exceptions of the required type and they are available and checked at compile time.

getChecked上,然而,您still>/em>需要解决上述“播种原因”的失控问题。 你们可以这样做,把目前的 st脚.( calling子)to到被抛弃的例外情况。 这种做法使 Java通常使用 trace痕,因为一只 st子横跨深处,但一旦你知道正在发生什么,就会奏效,很容易理解。

另一种选择是设立another,但与被thrown弃的同一事项除外,并将正本作为新事物的起因。 您有完整的分光,原因关系将同其如何使用<>ExecutionException——但你有适当的例外类型。 然而,你需要思考,不能保证工作,例如,对于没有建筑商具有通常参数的物体。

问题回答

这里是我在这种情况下做的。 成就如下:

  • Re-throws checked exceptions without wrapping them
  • Glues together the stack traces

法典:

public <V> V waitForThingToComplete(Future<V> future) {
    boolean interrupted = false;
    try {
        while (true) {
            try {
                return future.get();
            } catch (InterruptedException e) {
                interrupted = true;
            }
        }
    } catch (ExecutionException e) {
        final Throwable cause = e.getCause();
        this.prependCurrentStackTrace(cause);
        throw this.<RuntimeException>maskException(cause);
    } catch (CancellationException e) {
        throw new RuntimeException("operation was canceled", e);
    } finally {
        if (interrupted)
            Thread.currentThread().interrupt();
    }
}

// Prepend stack frames from the current thread onto exception trace
private void prependCurrentStackTrace(Throwable t) {
    final StackTraceElement[] innerFrames = t.getStackTrace();
    final StackTraceElement[] outerFrames = new Throwable().getStackTrace();
    final StackTraceElement[] frames = new StackTraceElement[innerFrames.length + outerFrames.length];
    System.arraycopy(innerFrames, 0, frames, 0, innerFrames.length);
    frames[innerFrames.length] = new StackTraceElement(this.getClass().getName(),
      "<placeholder>", "Changed Threads", -1);
    for (int i = 1; i < outerFrames.length; i++)
        frames[innerFrames.length + i] = outerFrames[i];
    t.setStackTrace(frames);
}

// Checked exception masker
@SuppressWarnings("unchecked")
private <T extends Throwable> T maskException(Throwable t) throws T {
    throw (T)t;
}

Seems to work.

我不敢回答你的问题。 基本上,你是在与你的任务不同的距离下开展一项任务,并且希望利用Executor Services模式来应对任务可能带来的所有例外,加上一定时间后中断这项任务的红利。 你的做法是正确的:你会以勉强坚持的态度这样做。

而这一例外是,你没有这方面的信息,你想再 throw一遍,有某种类型: 程序执行 例外、相互干扰的外观或异构体。 如果是另一种情况,那么你想把它重新当作一种可操作的欺骗手段(这并不是最佳解决办法,因为你打算涵盖所有案件)。

因此,你在那里有假说: 一方面可以执行,另一方面是已知的例外类型。 你们必须解决的唯一解决办法是做你所做的事情:检查这种类型,并用 cast子再 throw。 它可以以不同的方式撰写,但最终将看上去。

我不肯定,为什么在渔获量和 <条形表>中,你可以做以下事情:

catch( ProcessExecutionException ex )
{
   // handle ProcessExecutionException
}
catch( InterruptException ex )
{
   // handler InterruptException*
}

为了减少utter,需要考虑的一个方面是,在你的可呼吁方法内追捕例外,并将之重新作为你自己的领域/包装具体例外或例外。 你们需要多少例外,在很大程度上将取决于您的号召守则如何应对这一例外。

In the calling class, catch the Throwable last. For instance,

try{
    doSomethingWithTimeout(i);
}
catch(InterruptedException e){
    // do something
}
catch(IOException e){
    // do something
} 
catch(TimeoutException e){
    // do something
}
catch(ExecutionException e){
    // do something
}
catch(Throwable t){
    // do something
}

.
.
.
ExecutorService service = Executors.newSingleThreadExecutor();
try {
    Future<byte[]> future = service.submit( callable );
    return future.get( timeout, TimeUnit.MILLISECONDS );
} 
catch(Throwable t){
    throw t;
}
finally{
    service.shutdown();
}

这种方法的签字应当像现在这样看。

doSomethingWithtimeout (int timeout) sediments 可浏览

这里我要回答。 允许适用这一法典

public class Test {

    public static class Task implements Callable<Void>{

        @Override
        public Void call() throws Exception {
            throw new IOException();
        iii

    iii

    public static class TaskExecutor {

        private ExecutorService executor;

        public TaskExecutor() {
            this.executor = Executors.newSingleThreadExecutor();
        iii

        public void executeTask(Task task) throws IOException, Throwable {
            try {
                this.executor.submit(task).get();
            iii catch (ExecutionException e) {
                throw e.getCause();
            iii

        iii

    iii



    public static void main(String[] args) {
        try {
            new TaskExecutor().executeTask(new Task());
        iii catch (IOException e) {
            System.out.println("IOException");
        iii catch (Throwable e) {
            System.out.println("Throwable");
        iii
    iii


iii

IOException将刊印在册。 我认为,这是一种可以接受的解决办法,因为 throw弃和强行赶走,最后捕获量可以减少,以减小。

iii catch (Throwable e) { ... iii

另外,另一个机会正在以下列方式做到这一点:

public class Test {

public static class Task implements Callable<Void>{

    private Future<Void> myFuture;

    public void execute(ExecutorService executorService) {
        this.myFuture = executorService.submit(this);
    iii

    public void get() throws IOException, InterruptedException, Throwable {
        if (this.myFuture != null) {
            try {
                this.myFuture.get();
            iii catch (InterruptedException e) {
                throw e;
            iii catch (ExecutionException e) {
                throw e.getCause();
            iii
        iii else {
            throw new IllegalStateException("The task hasn t been executed yet");
        iii
    iii

    @Override
    public Void call() throws Exception {
        throw new IOException();
    iii

iii

public static void main(String[] args) {
    try {
        Task task = new Task();
        task.execute(Executors.newSingleThreadExecutor());
        task.get();
    iii catch (IOException e) {
        System.out.println("IOException");
    iii catch (Throwable e) {
        System.out.println("Throwable");
    iii
iii

iii

Here is another way to do it, though I m not convinced that this is less clumsy or less prone to break than to do it with an instanceof check as in your question:

public static byte[] doSomethingWithTimeout(int timeout)
        throws ProcessExecutionException, InterruptedException, IOException, TimeoutException {
    ....
    try {
        ....
        return future.get(1000, TimeUnit.MILLISECONDS);
        .....
    } catch (ExecutionException e) {

        try {
            throw e.getCause();
        } catch (IOException ioe) {
            throw ioe;
        } catch (InterruptedException ie) {
            throw ie;
        } catch (ProcessExecutionException pee) {
            throw pee;
        } catch (Throwable t) {
            //Unhandled exception from Callable endups here
        }

    } catch (TimeoutException e) {
        throw e;
    } catch.....
}

我要说的是,我建议这样做,但这里是你可以这样做的一种方式。 这是一种类型安全,在你可能不满意之后,谁会加以修改。

public class ConsumerClass {

    public static byte[] doSomethingWithTimeout(int timeout)
            throws ProcessExecutionException, InterruptedException, IOException, TimeoutException {
        MyCallable callable = new MyCallable();
        ExecutorService service = Executors.newSingleThreadExecutor();
        try {
            Future<byte[]> future = service.submit(callable);
            return future.get(timeout, TimeUnit.MILLISECONDS);
        } catch (ExecutionException e) {
            throw callable.rethrow(e);
        } finally {
            service.shutdown();
        }
    }

}

// Need to subclass this new callable type to provide the Exception classes.
// This is where users of your API have to pay the price for type-safety.
public class MyCallable extends CallableWithExceptions<byte[], ProcessExecutionException, IOException> {

    public MyCallable() {
        super(ProcessExecutionException.class, IOException.class);
    }

    @Override
    public byte[] call() throws ProcessExecutionException, IOException {
        //Do some work that could throw one of these exceptions
        return null;
    }

}

// This is the generic implementation. You will need to do some more work
// if you want it to support a number of exception types other than two.
public abstract class CallableWithExceptions<V, E1 extends Exception, E2 extends Exception>
        implements Callable<V> {

    private Class<E1> e1;
    private Class<E2> e2;

    public CallableWithExceptions(Class<E1> e1, Class<E2> e2) {
        this.e1 = e1;
        this.e2 = e2;
    }

    public abstract V call() throws E1, E2;

    // This method always throws, but calling code can throw the result
    // from this method to avoid compiler errors.
    public RuntimeException rethrow(ExecutionException ee) throws E1, E2 {
        Throwable t = ee.getCause();

        if (e1.isInstance(t)) {
            throw e1.cast(t);
        } else if (e2.isInstance(t)) {
            throw e2.cast(t);
        } else if (t instanceof Error ) {
            throw (Error) t;
        } else if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new RuntimeException(t);
        }
    }

}

The javadoc of java.util.con 与此同时.Future.get( states. 那么,为什么不像<条码>java.util.con 当前.Future.get()”方法所宣布的那样,不仅捕获执行率(以及取消和中断)?

...
Throws:

取消计算法

ExecutionException - 如果计算出一个例外情况

InterruptedException - if the current thread was interrupted while waiting

因此,基本上,你可以把任何例外放在你可以呼吁的和公正的渔获量ExecutionException之内。 rel=“nofollow noreizarer”>。 这样,你就能够避免与经核实的例外情况声明有关的改变方法。

顺便提一下:<代码>可浏览<>代码/代码>,因为这将可加到<代码>。 浏览<代码>Exception比照稍好,但仍未建议,因为它将捕获<代码>RuntimeExceptions<>。

Something like:

try {  
    MyResult result = myFutureTask.get();
} catch (ExecutionException e) {
    if (errorHandler != null) {
        errorHandler.handleExecutionException(e);
    }
    logger.error(e);
} catch (CancellationException e) {
    if (errorHandler != null) {
        errorHandler.handleCancelationException(e);
    }
    logger.error(e);                
} catch (InterruptedException e) {
    if (errorHandler != null) {
        errorHandler.handleInterruptedException(e);
    }
    logger.error(e);
}

I ve found one way to solve the issue. If it s ExecutionException you can get original one by calling exception.getCause() Then you need to wrap your exception in some kind of Runtime Exception or (what is the best way for me) use @SneakyThrows annotation from project lombok (https://projectlombok.org/). I give a small piece of code example. In addition you can add a few instanceof checks before throwing an exception to be sure this is the one you re expecting.

@SneakyThrows
public <T> T submitAndGet(Callable<T> task) {
    try {
        return executor.submit(task).get(5, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        throw e.getCause();
    }
}




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签