Читайте из BufferedReader для определенной продолжительности - PullRequest
0 голосов
/ 02 февраля 2019

Итак, я читаю из BufferedReader.Все идет хорошо, пока я не добавлю одно условие.Мне нужно читать из BufferedReader в течение определенного периода времени.

Это то, чем я сейчас занимаюсь.

while ((line = br.readLine()) != null
                    && System.currentTimeMillis() - start < maxReadTime.toMillis()) { 
    // doingSomethingHere()
}

Проблема: InputStream активен даже после истечения времени.Например - maxReadTime составляет 30 секунд.вход продолжает поступать в течение 20 секунд.В течение следующих 12 секунд активности нет.Теперь, когда поступает следующий ввод, поток открывается и закрывается только после того, как прочитал ввод.Однако я не обрабатываю этот ввод, потому что цикл завершается.

Что я ожидал или что мне нужно: поток закроется через 30 секунд.То есть, когда вход приходит на 32-й секунде, поток закрывается и не прослушивает какой-либо вход.

Я немного знаю о ExecutorService.Я не уверен, что это правильный путь.

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

В основном вы должны проверить, готов ли буфер перед вызовом readLine(), вызвав метод ready(), для InputStream check available() метод, который возвращает, как байты можно читать без блока.

Вот пример

import java.io.*;
import java.time.Duration;

public class Main {

    public static void main(String[] args) {
        final InputStream in =  System.in; //new FileInputStream(new File("/tmp/x"));
        final String out = readInput(in, Duration.ofSeconds(5));
        System.out.printf("m=main, status=complete, out=%s%n", out);
    }

    public static String readInput(InputStream in, Duration duration) {
        final long timestamp = System.currentTimeMillis();
        final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        final StringBuilder out = new StringBuilder();
        try {
            String line = null;
            while (true){
                if(Duration.ofMillis(System.currentTimeMillis() - timestamp).compareTo(duration) >=0 ){
                    System.out.println("m=readInput, status=timeout");
                    break;
                }
                if(!reader.ready()){
                    System.out.println("m=readInput, status=not ready");
                    sleep(1000);
                    continue;
                }
                line = reader.readLine();
                if(line == null){
                    System.out.println("m=readInput, status=null line");
                    break;
                }
                out.append(line);
                out.append('\n');
                System.out.printf("m=readInput status=read, line=%s%n" , line);
            }
            return out.toString();
        } catch (IOException e){
            throw new RuntimeException(e);
        } finally {
            System.out.println("m=readInput, status=complete");
        }
    }

    static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {}
    }

}

Если вы хотите сделать это в фоновом режиме, вы можете следовать этому примеру

package com.mageddo;

import java.io.*;
import java.util.concurrent.*;

public class Main {

public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
        final InputStream in =  System.in; //new FileInputStream(new File("/tmp/x"));
        final StringBuilder out = new StringBuilder();
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        final Future<String> promise = executor.submit(() -> readInput(in, out));
        try {
            final String result = promise.get(5, TimeUnit.SECONDS);
            System.out.printf("m=main, status=success, result=%s%n", result);
        } catch (TimeoutException e) {
            System.out.println("m=main, status=timeout");
            in.close();
            promise.cancel(true);
            System.out.println("Failed output: " + promise.get());
            e.printStackTrace();
        } finally {
            executor.shutdown();
            System.out.println("m=main, status=shutdown, out=" + out);
        }
    }

    public static String readInput(InputStream in, StringBuilder out) {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        try {
            String line = null;
            while (true){
                if(Thread.currentThread().isInterrupted()){
                    System.out.println("m=readInput status=interrupt signal");
                    break;
                }
                if(!reader.ready()){
                    System.out.println("m=readInput, status=not ready");
                    sleep(1000);
                    continue;
                }
                line = reader.readLine();
                if(line == null){
                    System.out.println("m=readInput, status=null line");
                    break;
                }
                out.append(line);
                out.append('\n');
                System.out.printf("m=readInput status=read, line=%s%n" , line);
            }
            return out.toString();
        } catch (IOException e){
            throw new RuntimeException(e);
        } finally {
            System.out.println("m=readInput, status=complete");
        }
    }

    static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

}

См. Ссылку

0 голосов
/ 02 февраля 2019

Просто поместите ваше условие таймера перед чтением из потока

while ((line = br.readLine()) != null) {
    boolean active = System.currentTimeMillis() - start < maxReadTime.toMillis();
    if (!active) {
        br.close();
    }         
    // doingSomethingHere()
}

В этом случае, если первое условие false (время истекло), второе не будет выполнено вообще

...