What is the best way to handle an ExecutionException?

后端 未结 11 1701
遇见更好的自我
遇见更好的自我 2020-12-04 12:07

I have a method that performs some task with a timeout. I use the ExecutorServer.submit() to get a Future object, and then I call future.get() with a timeout. This is workin

11条回答
  •  温柔的废话
    2020-12-04 12:54

    I wouldn't say I recommend this, but here is a way you can do it. It is type-safe and whoever comes to modify it after you will probably be unhappy with it.

    public class ConsumerClass {
    
        public static byte[] doSomethingWithTimeout(int timeout)
                throws ProcessExecutionException, InterruptedException, IOException, TimeoutException {
            MyCallable callable = new MyCallable();
            ExecutorService service = Executors.newSingleThreadExecutor();
            try {
                Future 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 {
    
        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
            implements Callable {
    
        private Class e1;
        private Class e2;
    
        public CallableWithExceptions(Class e1, Class 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);
            }
        }
    
    }
    

提交回复
热议问题