# Warten auf Eingabe



## Gast (10. Okt 2007)

Mein Problem ist folgendes:

Ich möchte das der Benutzer ein Ergebnis eingebit und wenn er es nach
einer gewissen Zeit nicht gemacht hat soll der nächste Befehl ausgeführt werden.

Ich danke schon mal im voraus.


----------



## André Uhres (10. Okt 2007)

Du könntest vor jeder Eingabe einen Thread starten, der z.B. 5 Sekunden schläft 
und danach selbst eine Eingabe tätigt.
Wenn nach der Eingabe der Thread noch lebt, dann hat der Benutzer etwas eingegeben 
und du kannst den Thread abbrechen.
Ansonsten hat der Thread etwas eingegeben.


----------



## SlaterB (10. Okt 2007)

gehts eigentlich um die Konsole oder eine GUI?

kann man denn in System.in was reinschreiben?
kann man ein read() darauf abbrechen?


----------



## André Uhres (11. Okt 2007)

>gehts eigentlich um die Konsole oder eine GUI?
Bei Fragen dieser Art geht's wohl meistens um die Konsole.

>kann man denn in System.in was reinschreiben?
Ja natürlich, sonst könnte man ja auch nix auslesen :wink:

>kann man ein read() darauf abbrechen?
Den read() kann man durch eine Eingabe abbrechen.


----------



## Gast (11. Okt 2007)

Erstmal danke für die Antworten!

Aber wie sieht dann der Quelltext aus und wann merkt der Thread das etwas eingegeben wurde 
bzw. ich müsste ja dann die Zeile Eingabe überspringen falls die Zeit vorüber ist.

Wie mache ich das konkret???


----------



## SlaterB (11. Okt 2007)

André Uhres hat gesagt.:
			
		

> Ja natürlich, sonst könnte man ja auch nix auslesen :wink:


hast du dafür ein Beispiel?


----------



## moormaster (11. Okt 2007)

Gast hat gesagt.:
			
		

> Erstmal danke für die Antworten!
> 
> Aber wie sieht dann der Quelltext aus und wann merkt der Thread das etwas eingegeben wurde
> bzw. ich müsste ja dann die Zeile Eingabe überspringen falls die Zeit vorüber ist.
> ...



Thread

```
...
  Thread.sleep(5000);

  if (!isInterrupted())
   // tätige Eingabe
```

Eingabe:

```
...
  // lese Benutzereingabe
  // breche Thread ab
  [Thread Referenz].interrupt();
```

Um das mal Beispielhaft zu skizzieren


----------



## moormaster (11. Okt 2007)

SlaterB hat gesagt.:
			
		

> André Uhres hat gesagt.:
> 
> 
> 
> ...



Im System.in landet normaler Weise alles, was der User in die Konsole des Programms eintippt... (oder was per Pipe in die Standardeingabe deines Programms geleitet wurde beim Programmaufruf vom Betriebssystem aus)


----------



## SlaterB (11. Okt 2007)

das ist kein Beispiel [zu 'selber per nebenläufigen Thread eine zusätzliche Eingabe erzeugen']


----------



## André Uhres (11. Okt 2007)

Hier ist ein funktionierendes Beispiel:

```
package basics;

/*
 * KonsoleTest.java
 */

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.logging.*;

public class KonsoleTest {

    private Scanner scanner;
    private String inputString;
    private Bedenkzeit bedenkzeit;
    private Thread bedenkzeitThread;

    public KonsoleTest() {
        scanner = new Scanner(System.in);
        inputString = "";
        System.out.println("*** Die Konsole muss bis Programmende den Fokus haben! ***");
        System.out.println("Bitte Text eingeben, end = Programmende");
        while (!inputString.equalsIgnoreCase("end")) {
            bedenkzeit = new Bedenkzeit();
            bedenkzeitThread = new Thread(bedenkzeit);
            bedenkzeitThread.start();
            inputString = scanner.next();
            bedenkzeit.setInput(true);
            if (inputString.toLowerCase().contains("xyz")) {
                //Eingabe vom Thread
                System.out.println("Upps! Bedenkzeit abgelaufen.");
            } else {
                //Benutzereingabe:
                System.out.println("OK: " + inputString);
            }
        }
    }

    public static void main(String[] args) {
        new KonsoleTest();
    }
}

class Bedenkzeit implements Runnable {

    private Robot robot;
    //Array für Tastaturdaten (um den Text zu schreiben):
    private int[] keyInput = {KeyEvent.VK_X, KeyEvent.VK_Y, KeyEvent.VK_Z};
    private boolean input;
    private int count;

    public Bedenkzeit() {
        //wenn die Bedenkzeit abgelaufen ist,
        //dann übernimmt einfach ein Roboter die Eingabe
        try {
            robot = new Robot();
        } catch (AWTException ex) {
            Logger.getLogger(Bedenkzeit.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void run() {
        while (!input && count < 100) {
            //warten auf Eingabe oder bis Bedenkzeit abgelaufen
            try {
                Thread.sleep(50);
            } catch (Exception ex) {
            }
            count++;
        }
        if (!input) {
            //falls keine Eingabe erfolgte..
            doInput(); //..übernimmt der Thread die Eingabe
        }
    }

    private void doInput() {
        for (int i = 0; i < keyInput.length; i++) {
            robot.keyPress(keyInput[i]);
            robot.keyRelease(keyInput[i]);
        }
        robot.keyPress(KeyEvent.VK_ENTER);
        robot.keyRelease(KeyEvent.VK_ENTER);
    }

    public void setInput(boolean b) {
        input = b;
    }
}
```
Oder so:

```
package basics;

/*
 * KonsoleTest2.java
 */

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.*;
import java.util.logging.*;

public class KonsoleTest2 {

    private Scanner scanner;
    private String inputString;
    private int count;

    public KonsoleTest2() {
        scanner = new Scanner(System.in);
        inputString = "";
        System.out.println("Bitte Text eingeben, end = Programmende");
        while (!inputString.equalsIgnoreCase("end")) {
            try {
                while (System.in.available() <= 0 && count < 100) {
                    //warten auf Eingabe oder bis Bedenkzeit abgelaufen
                    try {
                        Thread.sleep(50);
                    } catch (Exception ex) {
                    }
                    count++;
                }
                if (count < 100) {
                    //Benutzereingabe:
                    inputString = scanner.next();
                    System.out.println("OK: " + inputString);
                } else {
                    System.out.println("Upps! Bedenkzeit abgelaufen.");
                }
                count = 0;
            } catch (IOException ex) {
                Logger.getLogger(KonsoleTest2.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public static void main(String[] args) {
        new KonsoleTest2();
    }
}
```


----------



## SlaterB (11. Okt 2007)

na das ist ja sehr eingängig 
auch noch Fokus nötig

für andere Streams als System.in gibts dann aber endgültig keine Möglichkeit, etwas hineinzuschreiben/ ein read() abzubrechen?
ist definiert, was passiert, wenn ein read()-wartender Thread abgebrochen wird/ kann man den überhaupt beenden? (moormasters Posting traue ich mal nicht ganz  )
kann man den Stream dann noch verwenden?


----------



## moormaster (11. Okt 2007)

Wieso liest du denn mit read() blockierend ein? Einen Inpuitstream kann man doch per available() Methode Fragen, wieviele Bytes schon gelesen werden können, ohne dass der entsprechende read Aufruf (welcher dann höchstens diese Anzahl von Bytes einliest) das Programm blockiert.


----------



## SlaterB (11. Okt 2007)

> Wieso liest du denn mit read() blockierend ein? 

da es mir um die theoretischen Möglichkeiten geht, stellt sich diese Randbedingung nicht

für den Originalposter ist das allerdings eine deutlich einfachere Alternative als den Robot oder?
guter Tipp von dir 
einfach gar nicht read()-en sondern available()-n,
wenn innerhalb von 5 sec Daten da sind, dann diese lesen, sonst davon ausgehen, dass nichts eingetippt wurde,

dürfe ganz ohne Threads laufen, das Hauptprogramm kann mit
Thread.sleep(100); 100 ms schlafen gelegt werden,
das 50x, zwischendurch mit available() nachschauen, dann sind 5 sec vorbei

-----

meine Frage bezieht sich aber durchaus auf die Situation, wenn read() schon läuft,
Stream beenden ist etwas drastisch, dann dürfte wohl der wartende Thread wieder erwachen,
aber gehts auch mit weiterlebenden Stream?

mir fällt auf die Schnelle nur System.in als so wichtigen Stream ein, der nicht beendet werden sollte,
aber auch allgemein interessant


----------

