Будущее исключение TimeoutException каждый раз, когда оно истекает

#java #future #executorservice #timeoutexception

Вопрос:

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

 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;
    }
 

Приведенный выше код работает нормально, если нет тайм-аута. Но как только он создает исключение timeoutexception, все дальнейшие вызовы автоматически заканчиваются, даже если я получаю ответ. Я попытался увеличить время ожидания с 1 секунды до 2 секунд. Он снова продолжает выбрасывать исключение TimeoutException

Комментарии:

1. Отправьте тот же вызов снова и назначьте future результат.

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

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

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

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

Ответ №1:

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

Ответ №2:

Будущее Java упустило некоторые полезные методы, такие как 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());
}