Будущее выбрасывает TimeoutException каждый раз, когда истекает время ожидания

avatar
Juan
8 августа 2021 в 20:45
164
2
0

Я использую следующий код:

import java.util.concurrent
     senderSocket.send(datagramPacket);
            while (!test(packetToSend)) {
                senderSocket.send(datagramPacket);
            }

public boolean test(Packet sentPacket) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Callable<Packet> callable = new Callable() {

            public Packet call() throws Exception {
                //do operations you want
                Packet responsePacket = Helper.recievePacket(rSocket);
                while (responsePacket.isCorrupt() || responsePacket.getSequence() != sentPacket.getSequence()) {
                    responsePacket = Helper.recievePacket(rSocket);

                }
                System.out.println(new String(responsePacket.getData(),UTF_8));
                return responsePacket;

            }
        };
        Future<Packet> future = executor.submit(callable);
        try {
            future.get(1000, TimeUnit.MILLISECONDS);
            return true;
        } catch (TimeoutException e) {
            System.out.println("time-out");
            executor.shutdown();
            return false;

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return false;
    }

Приведенный выше код работает нормально, если нет тайм-аута. Но как только он выдает исключение тайм-аута, все дальнейшие вызовы автоматически истекают, даже если я получаю ответ. Я попытался увеличить время ожидания с 1 секунды до 2 секунд. Он снова продолжает бросать TimeoutException
Источник
Louis Wasserman
8 августа 2021 в 20:55
1

Снова отправьте тот же Callable и присвойте результату future.

Juan
8 августа 2021 в 21:15
0

@LouisWasserman Я могу сделать future = executor.submit(callable); внутри блока catch Но теперь, в случае TimeOutException, такое поведение больше не повторится. По сути, когда происходит тайм-аут, он снова должен делать senderSocket.send(datagramPacket); future = executor.submit(callable); . Я не уверен, как это делать.

Louis Wasserman
9 августа 2021 в 01:01
0

Вы должны сделать цикл, который продолжается до успеха.

Juan
9 августа 2021 в 01:30
0

@LouisWasserman Спасибо за это. У меня что-то работает. Но я получаю странное поведение. future. get(1000, TimeUnit.MILLISECONDS); Когда время будущего истекает. Время истекает каждый раз. Не уверен, почему это может быть так. Я только что обновил код в OP. Логика работает. Но единственная проблема заключается в том, когда происходит тайм-аут. Он просто выбрасывает исключение тайм-аута каждый раз

iggy
9 августа 2021 в 02:56
0

Если время ожидания истекло, вы не получили ожидаемого ответа. Он все еще сидит в розетке? Может ли удаленный конец обработать другой запрос, пока ответ еще не получен? Я бы посмотрел, что происходит в цикле «пока» в задаче.

Juan
9 августа 2021 в 03:36
0

Я попытаюсь отладить это таким образом. Но странная часть заключается в том, что вызываемый объект возвращает результат. Как может будущее время ожидания. Код мгновенно печатает значение System.out.println(new String(responsePacket.getData(),UTF_8));, а затем, если я даю тайм-аут даже 10 секунд, он все равно продолжает выдавать исключение TimeoutException.

Ответы (2)

avatar
Preston
9 августа 2021 в 02:14
0

В Java Future отсутствуют некоторые полезные методы, такие как onComplete().
Но мы можем написать его сами.

public static void main(String[] args) throws InterruptedException, ExecutionException {
    Future<String> f = null;
    
    onComplete(f, System.out::println);
}

static <T> void onComplete(Future<T> f, Consumer<T> callBack) throws InterruptedException, ExecutionException {
    while(!f.isDone()) {}
    callBack.accept(f.get());
}
avatar
Ashish Purohit
8 августа 2021 в 20:59
0

Почему бы вам не проверить с помощью futureisDone(). Это неблокирующий API. Если он возвращает true, вы можете вызвать future.get()