/** * Creates a TimeLimiter instance using the given executor service to execute method calls. * * <p><b>Warning:</b> using a bounded executor may be counterproductive! If the thread pool fills * up, any time callers spend waiting for a thread may count toward their time limit, and in this * case the call may even time out before the target method is ever invoked. * * @param executor the ExecutorService that will execute the method calls on the target objects; * for example, a {@link Executors#newCachedThreadPool()}. * @since 22.0 */ public static SimpleTimeLimiter create(ExecutorService executor) { return new SimpleTimeLimiter(executor); }
@Override protected void setUp() throws Exception { super.setUp(); service = SimpleTimeLimiter.create(executor); }
checkNotNull(interfaceType); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); checkArgument(interfaceType.isInterface(), "interfaceType must be an interface type"); final Set<Method> interruptibleMethods = findInterruptibleMethods(interfaceType); return newProxy(interfaceType, handler);
@Override public void runWithTimeout(Runnable runnable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException, InterruptedException { checkNotNull(runnable); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); Future<?> future = executor.submit(runnable); try { future.get(timeoutDuration, timeoutUnit); } catch (InterruptedException | TimeoutException e) { future.cancel(true /* mayInterruptIfRunning */); throw e; } catch (ExecutionException e) { wrapAndThrowRuntimeExecutionExceptionOrError(e.getCause()); throw new AssertionError(); } }
@CanIgnoreReturnValue @Override public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException, InterruptedException, ExecutionException { checkNotNull(callable); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); Future<T> future = executor.submit(callable); try { return future.get(timeoutDuration, timeoutUnit); } catch (InterruptedException | TimeoutException e) { future.cancel(true /* mayInterruptIfRunning */); throw e; } catch (ExecutionException e) { wrapAndThrowExecutionExceptionOrError(e.getCause()); throw new AssertionError(); } }
public <T> T newProxy(final T target, Class<T> interfaceType, final long timeoutDuration, final TimeUnit timeoutUnit) { checkNotNull(target); checkNotNull(interfaceType); checkNotNull(timeoutUnit); checkArgument(timeoutDuration > 0, "bad timeout: " + timeoutDuration); checkArgument(interfaceType.isInterface(), "interfaceType must be an interface type"); final Set<Method> interruptibleMethods = findInterruptibleMethods(interfaceType); InvocationHandler handler = new InvocationHandler() { public Object invoke(Object obj, final Method method, final Object[] args) throws Throwable { Callable<Object> callable = new Callable<Object>() { public Object call() throws Exception { try { return method.invoke(target, args); } catch (InvocationTargetException e) { Throwables.throwCause(e, false); throw new AssertionError("can't get here"); } } }; return callWithTimeout(callable, timeoutDuration, timeoutUnit, interruptibleMethods.contains(method)); } }; return newProxy(interfaceType, handler); }
SimpleTimeLimiter limiter = new SimpleTimeLimiter(); limiter.callWithTimeout(new Callable<Void>() {
private static Set<Method> findInterruptibleMethods(Class<?> interfaceType) { Set<Method> set = Sets.newHashSet(); for (Method m : interfaceType.getMethods()) { if (declaresInterruptedEx(m)) { set.add(m); } } return set; }
public Object invoke(Object obj, final Method method, final Object[] args) throws Throwable { Callable<Object> callable = new Callable<Object>() { public Object call() throws Exception { try { return method.invoke(target, args); } catch (InvocationTargetException e) { Throwables.throwCause(e, false); throw new AssertionError("can't get here"); } } }; return callWithTimeout(callable, timeoutDuration, timeoutUnit, interruptibleMethods.contains(method)); } };
private <T> T callWithTimeout( Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception { checkNotNull(callable); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); Future<T> future = executor.submit(callable); try { if (amInterruptible) { try { return future.get(timeoutDuration, timeoutUnit); } catch (InterruptedException e) { future.cancel(true); throw e; } } else { return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); } } catch (ExecutionException e) { throw throwCause(e, true /* combineStackTraces */); } catch (TimeoutException e) { future.cancel(true); throw new UncheckedTimeoutException(e); } }
@Override public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception { checkNotNull(callable); checkNotNull(timeoutUnit); checkArgument(timeoutDuration > 0, "timeout must be positive: %s", timeoutDuration); Future<T> future = executor.submit(callable); try { if (amInterruptible) { try { return future.get(timeoutDuration, timeoutUnit); } catch (InterruptedException e) { future.cancel(true); throw e; } } else { return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); } } catch (ExecutionException e) { throw throwCause(e, true); } catch (TimeoutException e) { future.cancel(true); throw new UncheckedTimeoutException(e); } }
= findInterruptibleMethods(interfaceType); return newProxy(interfaceType, handler);
SimpleTimeLimiter timeLimiter = new SimpleTimeLimiter(); return timeLimiter.callWithTimeout(consumeCaller, timeout, TimeUnit.MILLISECONDS, true); } catch (UncheckedTimeoutException e) { log.debug("BlockingConsumeById(messageId=" + messageId + ") failed due to timeout.", e);
private static Set<Method> findInterruptibleMethods(Class<?> interfaceType) { Set<Method> set = Sets.newHashSet(); for (Method m : interfaceType.getMethods()) { if (declaresInterruptedEx(m)) { set.add(m); } } return set; }
@Override public Object invoke(Object obj, final Method method, final Object[] args) throws Throwable { Callable<Object> callable = new Callable<Object>() { @Override public Object call() throws Exception { try { return method.invoke(target, args); } catch (InvocationTargetException e) { throwCause(e, false); throw new AssertionError("can't get here"); } } }; return callWithTimeout(callable, timeoutDuration, timeoutUnit, interruptibleMethods.contains(method)); } };
private <T> T callWithTimeout( Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception { checkNotNull(callable); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); Future<T> future = executor.submit(callable); try { if (amInterruptible) { try { return future.get(timeoutDuration, timeoutUnit); } catch (InterruptedException e) { future.cancel(true); throw e; } } else { return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); } } catch (ExecutionException e) { throw throwCause(e, true /* combineStackTraces */); } catch (TimeoutException e) { future.cancel(true); throw new UncheckedTimeoutException(e); } }
@Override public <T> T callWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) throws Exception { checkNotNull(callable); checkNotNull(timeoutUnit); checkArgument(timeoutDuration > 0, "timeout must be positive: %s", timeoutDuration); Future<T> future = executor.submit(callable); try { if (amInterruptible) { try { return future.get(timeoutDuration, timeoutUnit); } catch (InterruptedException e) { future.cancel(true); throw e; } } else { return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); } } catch (ExecutionException e) { throw throwCause(e, true); } catch (TimeoutException e) { future.cancel(true); throw new UncheckedTimeoutException(e); } }
@Override public void runUninterruptiblyWithTimeout( Runnable runnable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException { checkNotNull(runnable); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); Future<?> future = executor.submit(runnable); try { Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); } catch (TimeoutException e) { future.cancel(true /* mayInterruptIfRunning */); throw e; } catch (ExecutionException e) { wrapAndThrowRuntimeExecutionExceptionOrError(e.getCause()); throw new AssertionError(); } }
@CanIgnoreReturnValue @Override public <T> T callUninterruptiblyWithTimeout( Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException, ExecutionException { checkNotNull(callable); checkNotNull(timeoutUnit); checkPositiveTimeout(timeoutDuration); Future<T> future = executor.submit(callable); try { return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); } catch (TimeoutException e) { future.cancel(true /* mayInterruptIfRunning */); throw e; } catch (ExecutionException e) { wrapAndThrowExecutionExceptionOrError(e.getCause()); throw new AssertionError(); } }