Примените контроль времени ожидания вокруг операции Java - PullRequest
16 голосов
/ 12 февраля 2011

Я использую стороннюю библиотеку Java для взаимодействия с REST API.REST API иногда может занять много времени для ответа, что в конечном итоге приводит к выдаче java.net.ConnectException.

Я хотел бы сократить период ожидания, но у меня нет средств для изменения сторонней библиотеки.

Я хотел бы применить некоторую форму контроля времени ожидания при вызове метода Java, чтобы я мог определить, в какой момент отказаться от ожидания.

Это не имеет прямого отношения к тайм-аутам сети,Я хотел бы иметь возможность попытаться выполнить операцию и отказаться от нее после определенного времени ожидания.

Следующее ни в коем случае не является допустимой Java, но концептуально демонстрирует, чего я хотел бы достичь:

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

Ответы [ 7 ]

15 голосов
/ 12 февраля 2011

Я рекомендую TimeLimiter из библиотеки Google Guava.

3 голосов
/ 20 декабря 2014

Это, вероятно, текущий способ, как это должно быть сделано с простой Java:

3 голосов
/ 12 февраля 2011

Не существует общего механизма тайм-аута, действительного для произвольных операций.

Пока ... есть один ... с помощью Thread.stop (Throwable). Он работает и безопасен, но ваша личная безопасность находится под угрозой, когда злая толпа сталкивается с вами.

// 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
} 
1 голос
/ 03 января 2013

Вот класс утилиты, который я написал, который должен делать свое дело, если я что-то пропустил.К сожалению, он может возвращать только общие объекты и генерировать общие исключения.Другие могут иметь лучшие идеи о том, как этого добиться.

public abstract class TimeoutOperation {

long timeOut = -1;
String name = "Timeout Operation"; 

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public long getTimeOut() {
    return timeOut;
}

public void setTimeOut(long timeOut) {
    this.timeOut = timeOut;
}

public TimeoutOperation (String name, long timeout) {
    this.timeOut = timeout;
}

private Throwable throwable;
private Object result;
private long startTime;

public Object run () throws TimeoutException, Exception {
    Thread operationThread = new Thread (getName()) {
        public void run () {
            try {
                result = doOperation();
            } catch (Exception ex) {
                throwable = ex;
            } catch (Throwable uncaught) {
                throwable = uncaught;
            }
            synchronized (TimeoutOperation.this) {
                TimeoutOperation.this.notifyAll();
            }   
        }
        public synchronized void start() {
            super.start();
        }
    };
    operationThread.start();
    startTime = System.currentTimeMillis();
    synchronized (this) {
        while (operationThread.isAlive() && (getTimeOut() == -1 || System.currentTimeMillis() < startTime + getTimeOut())) {
            try {
                wait (1000L);
            } catch (InterruptedException ex) {}
        }   
    }   
    if (throwable != null) {
        if (throwable instanceof Exception) {
            throw (Exception) throwable;
        } else if (throwable instanceof Error) {
            throw (Error) throwable;
        }   
    }   
    if (result != null) {
        return result;
    }   
    if (System.currentTimeMillis() > startTime + getTimeOut()) {
        throw new TimeoutException("Operation '"+getName()+"' timed out after "+getTimeOut()+" ms");
    } else {
        throw new Exception ("No result, no exception, and no timeout!");
    }
}

public abstract Object doOperation () throws Exception;

public static void main (String [] args) throws Throwable {
    Object o = new TimeoutOperation("Test timeout", 4900) {
        public Object doOperation() throws Exception {
            try {
                Thread.sleep (5000L);
            } catch (InterruptedException ex) {}
            return "OK";
        }
    }.run();
    System.out.println(o);
}   

}
1 голос
/ 12 февраля 2011

Вы можете использовать Таймер и TimerTask .

0 голосов
/ 29 ноября 2018

Теперь у нас есть прекрасное CompletableFuture, здесь приложение для достижения того, о чем просили.

CompletableFuture.supplyAsync(this::foo).get(15, TimeUnit.SECONDS)
0 голосов
/ 12 февраля 2011
    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);
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...