Apply timeout control around Java operation

2020-06-01 03:38发布

I'm using a third party Java library to interact with a REST API. The REST API can sometimes take a long time to respond, eventually resulting in a java.net.ConnectException being thrown.

I'd like to shorten the timeout period but have no means of modifying the third party library.

I'd like to apply some form of timeout control around the calling of a Java method so that I can determine at what point to give up waiting.

This doesn't relate directly to network timeouts. I'd like to be able to try and perform an operation and be able to give up after a specified wait time.

The following is by no means valid Java but does conceptually demonstrate what I'd like to achieve:

try {
    Entity entity = new Entity();
    entity.methodThatMakesUseOfRestApi();
} catch (<it's been ages now, I don't want to wait any longer>) {
    throw TimeoutException();
}

标签: java timeout
7条回答
Evening l夕情丶
2楼-- · 2020-06-01 03:57

This is probably the current way how this should be done with plain Java:

public String getResult(final RESTService restService, String url) throws TimeoutException {
    // should be a field, not a local variable
    ExecutorService threadPool = Executors.newCachedThreadPool();

    // Java 8:
    Callable<String> callable = () -> restService.getResult(url);

    // Java 7:
    // Callable<String> callable = new Callable<String>() {
    //     @Override
    //     public String call() throws Exception {
    //         return restService.getResult(url);
    //     }
    // };

    Future<String> future = threadPool.submit(callable);
    try {
        // throws a TimeoutException after 1000 ms
        return future.get(1000, TimeUnit.MILLISECONDS);
    } catch (ExecutionException e) {
        throw new RuntimeException(e.getCause());
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new TimeoutException();
    }
}
查看更多
萌系小妹纸
3楼-- · 2020-06-01 03:58

There is no general timeout mechanism valid for arbitrary operations.

While... there is one... by using Thread.stop(Throwable). It works and it's thread safe, but your personal safety is in danger when the angry mob confronts you.

// realizable 
try
{
    setTimeout(1s);  // 1
    ... any code     // 2 
    cancelTimeout(); // 3
}
catch(TimeoutException te)
{
    // if (3) isn't executed within 1s after (1)
    // we'll get this exception
} 
查看更多
劳资没心,怎么记你
4楼-- · 2020-06-01 04:03

I recommend TimeLimiter from Google Guava library.

查看更多
手持菜刀,她持情操
5楼-- · 2020-06-01 04:03

Now we have our nice CompletableFuture , here an application to achieve what was asked.

CompletableFuture.supplyAsync(this::foo).get(15, TimeUnit.SECONDS)
查看更多
beautiful°
6楼-- · 2020-06-01 04:09

You could use a Timer and a TimerTask.

查看更多
小情绪 Triste *
7楼-- · 2020-06-01 04:10
    static final int NUM_TRIES =4;
    int tried =0;
    boolean result =false;
    while (tried < NUM_TRIES && !result)
    {
    try {
        Entity entity = new Entity();

            result = entity.methodThatMakesUseOfRestApi();


    }  
     catch (<it's been ages now, I don't want to wait any longer>) {
        if ( tried == NUM_TRIES)
        {
           throw new TimeoutException();
        }

    }
                tried++;
            Thread.sleep(4000);
  }
查看更多
登录 后发表回答