1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| public class TimeoutScanner implements AutoCloseable {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final BufferedReader reader;
private final InputStream is;
public TimeoutScanner() {
this.is=System.in;
this.reader = new BufferedReader(new InputStreamReader(System.in));
}
@Override
public void close() {
executor.shutdownNow(); // arrêt de l'exécuteur sans attendre que les tâches en cours soient terminées
}
public Optional<String> readline(int timeout, TimeUnit timeunits) {
AtomicBoolean stop = new AtomicBoolean(); // permet d'arrêter la boucle de lecture lors d'une exception
FutureTask<String> readline = new FutureTask<>(()-> {
boolean ok=false; // vrai si on a lu une ligne, faux sinon
String response=null;
do {
if ( reader.ready() && !stop.get() && !Thread.currentThread().isInterrupted() ) { // on ne lit que s'il y a quelque chose à lire et qu'on a pas annulé la lecture
response = reader.readLine(); // on lit
ok=true; // on dit qu'on a lu
}
} while( !ok && !Thread.currentThread().isInterrupted()); // tant qu'on a pas lu et qu'on a pas
return response;
});
executor.submit(readline); // lance la tâche
try {
return Optional.of(readline.get(5, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
readline.cancel(true); // force l'annulation de la tâche
stop.set(true); // pour éviter de commencer à lire et bloquer le thread alors qu'on a annuler
try {
while ( is.available()>0 ) reader.read(); // vide le tampon (si l'utilisateur à commencer à taper sans faire entrée)
} catch (IOException e1) {
}
return Optional.empty();
}
}
public Optional<Integer> readInteger(long timeout, TimeUnit timeunits, String errorMessage) {
AtomicBoolean stop = new AtomicBoolean();
FutureTask<Integer> readline = new FutureTask<>(()-> {
boolean ok=false;
Integer response=null;
do {
if ( reader.ready() && !stop.get() && !Thread.currentThread().isInterrupted() ) {
try {
response = Integer.valueOf(reader.readLine());
ok=true;
}
catch(NumberFormatException e) {
System.out.println(errorMessage);
}
}
} while( !ok && !Thread.currentThread().isInterrupted());
return response;
});
executor.submit(readline);
try {
return Optional.of(readline.get(5, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
readline.cancel(true);
stop.set(true);
try {
while ( is.available()>0 ) reader.read();
} catch (IOException e1) {
}
return Optional.empty();
}
}
public static void main(String[] args) {
try(TimeoutScanner reader = new TimeoutScanner()) {
System.out.println("Vous avez 5 secondes pour taper votre texte...");
Optional<String> text = reader.readline(5, TimeUnit.SECONDS); // lit une chaîne au clavier en attendant max 5 secondes
if ( text.isPresent() ) { // si une saisie a été effectuée
System.out.println("Votre saisie : " + text.get());
}
else { // si aucune saisie n'a été effectuée
System.out.println("Trop tard");
}
System.out.println("Vous avez 5 secondes pour taper un nombre...");
Optional<Integer> value = reader.readInteger(5, TimeUnit.SECONDS, "Un nombre on vous a dit !!!");
if ( value.isPresent() ) {
System.out.println("Votre saisie : " + value.get());
}
else {
System.out.println("Trop tard");
}
}
}
} |
Partager