# Mit Thread arbeitende Maschine



## Steps (20. Okt 2007)

Hallo, hab mal ein Problem bitte, aber wusste nicht genau wo das hingehört! Wäre trotzdem für Hilfe dankbar, weil ich nicht wirklich ein Programmiermeister bin!!!!!

*Die Aufgabenstellung: *


```
public static void main(){
            Wartet schon mit System.in.read() auf eine Enter-Eingabe zum sarten. Ist das erstmal richtig?
            Startet ihren Ablauf.......
         }
```

Die main() Methode soll andauernd wiederholt werden auch immer Benutzereingaben entgegennehmen. Die Betätigung einer Taste soll den Vorgang starten, beim erneuten betätigen einer Taste soll der Vorgang beendet werden. Die main()-Methode soll in einem Nebenläufigen Prozess (Thread) laufen. Leite eine Klasse Maschine von Thread ab und überschreibe die run()-Methode. 
*
Mein Lösungsansatz: *


```
private static class Maschine extends Thread {
		
		public Maschine(IOPortAccess i) {
			super();
                        this.i=i;
		}
		public void run(){

			while (true) {
                            while(System.in.read()==-1);
                            main();
                            while(System.in.read()==-1);
			}
		}
	}
```


Also beim Aufruf der run()-Methode wartet man immer jetzt auf ein Enter, ab wo es anfangen soll. Und mit einem Enter mach ich schluss?

Ich hab keine Ahnung ob das jetzt richtig sein soll. Es kam in einer Klausur drann, die ich jetzt versuche alleine zu lösen und wozu wir keine Lösungen mehr bekommen haben! Es ist nur ein bischen Merkwürdig, dass es 20% einer Arbeit ausmacht, also man bekommt dafür 7 punkte. Klingt aber eni bischen viel für sowas, daher dachte ich mir, das ist falsch.

falls ihr näheres über die Aufgabenstellung braucht, dann kann ich sie Auch ganz abtippen. Dachte aber das wäre nciht nötig, weil ich die main schon habe!


----------



## Guest (20. Okt 2007)

Eher wie folgt. Die Main-Methode soll ja ständig laufen.
	
	
	
	





```
public class MaschineTest {

   static class Maschine extends Thread {
      private Boolean running = Boolean.TRUE;

      public synchronized void kill() {
         synchronized (running) {
            running = Boolean.FALSE;
         }
      }

      public void run() {
         for (;;) {
            synchronized (running) {
               if (!running) {
                  break;
               }
            }
            main();
         }
      }
   }
   
   private static void main() {
      try {
         System.out.println("main");
         Thread.sleep(250);
      }
      catch (InterruptedException e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {
      Maschine machine = null;
      for (;;) {
         try { 
            System.in.read();
            if(machine == null) {
               machine = new Maschine();
               machine.start();
            }
            else {
               machine.kill();
               machine = null;
            }
         }
         catch (java.io.IOException e) {
            e.printStackTrace();
         }
      }
   }
}
```


----------



## Guest (20. Okt 2007)

Kleine Korrektur. Mach das synchronized in der Methodensignatur von kill() weg.
	
	
	
	





```
public void kill() { 
   synchronized (running) { 
      running = Boolean.FALSE; 
   } 
}
```


----------



## Steps (20. Okt 2007)

naja das mit dem ....

synchronized (running)
und kill() hatten wir noch garnicht!! und ich weis auch nciht was das bedeuten soll??

habe auf eine einfache lösung gehofft, da wir das ganze aus dem Kopf aufs Papier bringen müsen in einer Klausur und keine externen Hilfsmittel zur verfügung haben. Unser Lehrer macht übrigens nie etwas schweres...

Und diese try catch blöcke müssen wir auch nciht haben.... nur eben das wesentliche.

Und jetzt zu meinen Fragen sofern keine Anderen Hilfestellungen gegeben sind, versuche ich es einfach zu verstehen...

Also in der  public static void main(String[] args)  wird sozusagen nur ein maschineobjekt von der klasse erzeugt, damit ich die klasse ( den Thread) starten kann.?

Das verstehe ich überhaupt nicht?  also es wird nur main ausgegeben und dann gewartet?? Wieso?

```
private static void main() {
      try {
         System.out.println("main");
         Thread.sleep(250);
      }
      catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
```



```
public synchronized void kill() {
         synchronized (running) {
            running = Boolean.FALSE;
         }
      } 
public void run() {
         for (;;) {
            synchronized (running) {
               if (!running) {
                  break;
               }
            }
            main();
         }
      }
```

Das for(; ist genau dasselbe wie while(true) ?? Nehme ich an, damit es halt immer wiederdurchläuft eben?

Was bedeutet überhaupt dieses running und woher kommt das und syschronized kann cih auch 0 damit anfangen.




Sorry dass ich grad mal garnix raff, aber hab schon gesagt, ihr habts mit nem anfänger zu tun. Und ich bedanke mcih trotzdem Für die Mühe und Hilfsbereitschaft. Find ich toll


----------



## Guest (21. Okt 2007)

OK, gehen wir es mal der Reihe nach durch. (Ich habe es etwas anders gestaltet als in meiner ersten Antwort)

Das hier ist grob umschrieben die Aufgabe





> Die main() Methode soll andauernd wiederholt werden auch immer Benutzereingaben entgegennehmen.
> Die Betätigung einer Taste soll den Vorgang starten, beim erneuten betätigen einer Taste soll
> der Vorgang beendet werden. Die main()-Methode soll in einem Nebenläufigen Prozess (Thread) laufen.
> Leite eine Klasse Maschine von Thread ab und überschreibe die run()-Methode.


Wir haben irgendeine main() Methode, die in einer Endlosschleife laufen, Benutzereingabe entgegennehmen
und irgendeine Aktion ausführen soll.
	
	
	
	





```
public class MaschineTest
{
   public static void main(String[] args) throws Exception // Das da ist wegen System.in.read(); nötig.
   {
      // Endlos wiederholen
      for (;;)
      {
         // Auf Eingabe warten (auf Console leider eine Bestätigung mit Return nötig)
         System.in.read();
         // Aktion ausführen (was auch immer)
         ausgabe();
      }
   }
}
```
Das hier ist etwas missverständlich ausgedrück, soll aber heissen, dass die eigentliche
Aktion (im Beispiel die Methode ausgabe()) in einem getrennten Thread laufen soll.





> Die main()-Methode soll in einem Nebenläufigen Prozess (Thread) laufen.





> Leite eine Klasse Maschine von Thread ab und überschreibe die run()-Methode.




```
class Maschine extends Thread
{
   public void run()
   {
      do 
      {
         // Aktion ständig wiederholen
         ausgabe();
      }
      while(true); // Beachte, dass das hier nie endet!
   }

   private void ausgabe()
   {
      System.out.println("ausgabe");
   }
}
```
Wir haben bisher also folgendes
	
	
	
	





```
public class MaschineTest
{
   public static void main(String[] args) throws Exception // Das da ist wegen System.in.read(); nötig.
   {
      Maschine maschine = null;
      // Endlos wiederholen
      for (;;)
      {
         // Auf Eingabe warten (auf Console leider eine Bestätigung mit Return nötig)
         System.in.read();
         // Nebenläufigen Prozess (Thread) erzeugen
         maschine = new Maschine();
         // und starten
         maschine.start();
         // Auf Eingabe zum Beenden warten (auf Console leider eine Bestätigung mit Return nötig)
         System.in.read();
         // [1] Nebenläufigen Prozess beenden
      }
   }
}

class Maschine extends Thread
{
   public void run()
   {
      do 
      {
         // Aktion ständig wiederholen
         ausgabe();
         // [2] Schleife auf Anforderung verlassen (damit wird der Thread beendet)
      }
      while(true); // Beachte, dass das hier nie endet!
   }

   private void ausgabe()
   {
      System.out.println("ausgabe");
   }
}
```
OK, soweit so gut. Du hast aber zwei kleine Probleme (siehe [1] und [2])

[1] Nebenläufigen Prozess beenden
[2] Schleife auf Anforderung verlassen (damit wird der Thread beendet und somit auch [1] erledigt)

Einen Thread kannst du nicht einfach so abschiessen (siehe Thread.stop(), Thread.interrupt()
in der API), daher musst du in dem Thread vermerken, ob es weiterhin laufen soll oder nicht.

Das kannst du mit einer zusätzlichen Variable in dem Thread erreichen.  (siehe "immerNochAusfuehren" in Maschine)
	
	
	
	





```
public class MaschineTest
{
   public static void main(String[] args) throws Exception // Das da ist wegen System.in.read(); nötig.
   {
      Maschine maschine = null;
      // Endlos wiederholen
      for (;;)
      {
         // Auf Eingabe warten (auf Console leider eine Bestätigung mit Return nötig)
         System.in.read();
         // Nebenläufigen Prozess (Thread) erzeugen
         maschine = new Maschine();
         // und starten
         maschine.start();
         // Auf Eingabe zu Beenden warten (auf Console leider eine Bestätigung mit Return nötig)
         System.in.read();
         // Nebenläufigen Prozess beenden
         maschine.beenden();
      }
   }
}

class Maschine extends Thread
{
   private Boolean immerNochAusfuehren = Boolean.TRUE;

   public void beenden()
   {
      // Ausführung als beendet markieren.
      immerNochAusfuehren = Boolean.FALSE;
   }

   public void run()
   {
      // Aktion ständig wiederholen, solange immerNochAusfuehren = TRUE
      do
      {
         ausgabe();
      }
      while( immerNochAusfuehren );
   }

   private void ausgabe()
   {
      System.out.println("ausgabe");

      try
      {
         // 250ms warten, damit die Ausgabe nicht so schnell geht
         Thread.sleep(250);
      }
      catch(Exception e)
      {
         e.printStackTrace();
      }
   }
}
```
Vergiss das Synchronized für's erste. 
Ich habe es mit dem "Programmieren auf Papier" während des Studiums immer gehasst.
Sobald man versucht Backspace auf Papier zu machen, merkt man, dass es Irrsinn ist.


----------



## Steps (21. Okt 2007)

Achso, in deinem Beispiel beendet die 2. Entertaste nur die Run-Methode, die andere läuft aber immer noch weiter. 


			
				Anonymous hat gesagt.:
			
		

> [1] Nebenläufigen Prozess beenden
> [2] Schleife auf Anforderung verlassen (damit wird der Thread beendet und somit auch [1] erledigt)



Wenn ich mich erstmal nicht um den Hauptprozess kümmern will,  könnte ich doch einfach schreiben: 


```
public class MaschineTest
{
   public static void main(String[] args) throws Exception
   {
      Maschine maschine = null;
      for (;;){
         System.in.read();
         maschine = new Maschine();
         maschine.start();
         System.in.read();
         maschine.stop();
      }
   }
}

   public static class Maschine extends Thread{

     public void run(){
        while( i=0)){
             init();
             if(System.in.read()== TASTE(n) für nochmal durchlaufen);
             main();
        }
     }
   }
}
```

Noch ne ganz kleine Frage: Für Maschinen braucht man doch so ein Notfallaus. Sollte man das mit Strom aus machen, oder lässt sich das ganz einfach durchs Programmieren Regeln in der Theorie? Wenn ich jetzt das zweite mal Enter drücke, beendet der thread dann sofort alles, oder wird dann nochmal die mainmethode zuendegeführt? oder muss ich dazu maschine.interrupt(); nehmen, oder erst dann noch die main-methode umschreiben?


Aber habs im großen und ganzen jetzt dank dir geschafft =), viiiiiielen viiielen dank!!!!! Find ich supernett !


----------



## Guest (21. Okt 2007)

Hallo,

wie ich schon schrieb, die stop-Merthode solltest du nicht verwenden. 
Siehe dazu http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#stop() 
bzw. http://java.sun.com/j2se/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

Die Hauptschleife soll auch, ohne Unterbrechung, in der Klasse Maschine laufen, daher keine Tastenabfrage
innerhalb der Schleife.


----------

