In einem Thread Endlosschleife beenden

BasBeg

Aktives Mitglied
Hallo zusammen,

ich hab eine Frage zu meiner Klasse. Es gibt insgesamt vier Klassen, Car, Queue, Garage und
Java:
public class CarMechanic extends Thread {

    private Queue q;
    private int id;

    CarMechanic(Queue q, int id) {
        this.q = q;
        this.id = id;
    }

    public void run() {
        while (true) {
            Car c = q.getCar();
            if (c != null) {
                c.repair(id);
            } else {
                try {
                    sleep(1000);
                } catch (Exception ex) {
                    System.out.println(ex.getMessage());
                }

            }
        }
    }
}

Meine Frage ist, wie bekomme ich in der run Methode die Endlosschleife weg? Meine Vorstellung wäre, ich möchte die size der Queue abfragen und sobald sich der Zustand der Queue ändert, sollen meine Mechaniker arbeiten. Sobald die Queue dann leer ist, soll das Programm beendet werden.

Für ein solche vorhaben müsste ich ein Observer nutzen oder geht das irgendwie auch noch anders?

In der Garage erstelle ich die Mechaniker, dort gibt es eine Liste mit Autos (Cars) und die Mechaniker nehmen sich Autos aus dieser Liste. Wie oben beschrieben wäre es toll wenn ich diese Endlosschleife beenden könnte. Mir fällt dazu aber nur Observer ein. Ist das vielleicht zu "Overkill" geht es auch "einfacher"? Würde mich sehr über eine Antwort von euch freuen :)

Hier auch noch sehr gerne die restlichen Klassen:
Garage:
Java:
public class Garage {

    private Queue q = new Queue();

    public Garage() {
        for (int i = 0; i < 10; i++)
            new CarMechanic(q, i).start();
    }

    public void dropCar(Car car) {
        q.putCar(car);
    }
    
    public static void main(String[] args) {
        Garage g = new Garage();
        for(int i = 0; i < 120; i++)
            g.dropCar(new Car());
        
    }

}

Queue:
Java:
import java.util.ArrayList;

public class Queue {
    private ArrayList<Car> element;

    Queue() {
        element = new ArrayList<>();
    }

    public synchronized void putCar(Car c) {
        element.add(c);
    }

    public synchronized Car getCar() {
        if (element.isEmpty())
            return null;
        Car c = element.get(0);
        element.remove(0);
        return c;
    }

    public boolean isEmpty() {
        return element.isEmpty();
    }

}
(Die Methode putCar müsste nicht Synchronized sein, weiß ich, hab es aber jetzt so gelassen :D

Car:
Java:
public class Car {
    private int id;
    static int i = 0;

    Car() {
        id = i++;
    }

    public void repair(int id) {
        System.out.println("Mechaniker " + id + ": Auto " + this.id + " wird repariert");
        try {
            Thread.sleep((int) (Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getId() {
        return id;
    }
}
 

Oneixee5

Top Contributor
Nur als Hinweis außerhalb des Themas.
Dieser Code:
Java:
        public synchronized Car getCar() {
            if (element.isEmpty())
                return null;
            Car c = element.get(0);
            element.remove(0);
            return c;
        }
ist äquivalent zu:
Java:
        public synchronized Car getCar() {
            if (this.element.isEmpty()) {
                return null;
            }
            return this.element.remove(0);
        }
 

BasBeg

Aktives Mitglied
Du hast doch Queue.isEmpty() implementiert. Das wäre doch die Abbruchbedingung die du suchst oder verstehe ich dich gerade falsch?
Das Problem ist, das die Threads (Mechaniker) vorher los laufen und noch keine Daten in der Queue vorhanden sind.

Eine BlockingQueue waere eine Moeglichkeit. Diese blockiert den Thread dann solange bis es etwas zum entnehmen gibt.
Klaro könnte man andere Klassen nutzen, dass sollen wir aber nicht ;-)
 

BasBeg

Aktives Mitglied
Im Garage Konstruktor erzeuge ich doch die Threads. Doch wenn die Threads in der run Methode die Variable überprüfen würden, dann wäre dort doch noch nichts! Das ganze kommt doch erst später oder sehe ich das Falsch?

Java:
Garage g = new Garage();  //hier erzeugen wir die Threads, diese laufen schon mal los
        for(int i = 0; i < 120; i++)
            g.dropCar(new Car()); //hier kommt das erste Auto in die Queue, somit ist die Queue oben noch leer!
 

mihe7

Top Contributor

Oneixee5

Top Contributor
Im Garage Konstruktor erzeuge ich doch die Threads. Doch wenn die Threads in der run Methode die Variable überprüfen würden, dann wäre dort doch noch nichts! Das ganze kommt doch erst später oder sehe ich das Falsch?
Ich verstehe das Problem nicht. Ein Mechaniker kommt morgens zur Arbeit in die Garage. Sollte kein Car in der Garage sein, welches repariert werden muss, dann wartet er bis es Arbeit gibt. Kommt dann ein Kunde wird er sofort bedient. Kommen mehrere Kunden in kurzer Zeit hintereinander werden sie sequentiell bedient. Ist kein Car zur Reparatur vorhanden, dann muss der Mechaniker von zeit zu Zeit nachsehen ob evtl. Arbeit vorhanden ist.
Man könnte das auch über wait() und notify() lösen, statt mit Thread.sleep aber das Problem bleibt. Der Thread muss laufen um Arbeit zu verrichten oder in Bereitschaft zu sein. Für eine Lösung mit wait() und notify() müsste aber wahrscheinlich einiges umgebaut werden. ich habe so etwas auch schon ewig nicht mehr gemacht. Das muss man heute praktisch nicht mehr, da sich Java auch immer weiter entwickelt, s. BlockingQueue.
 

X5-599

Top Contributor
Es geht ihm mit der Aussage wahrscheinlich um die Abbruchbedingung Queue#isEmpty anstelle der Endlosschleife. Zumindest hab ich das so verstanden. Die kann er halt nicht nehmen weil zu beginn des Programms noch keine Elemente in der Queue liegen.

Ansonsten: ja, der Thread muss blockieren bis es etwas zu tun gibt (Queue ist nicht mehr leer). Das kann auf verschiedene Weise gemacht werden. Wait/Notify hab ich persönlich noch nie so wirklich mit gearbeitet. Als einfache Lösung käme mir hier ein Polling mittels Thread#sleep in den Sinn.

Da sähe die run Methode in etwa so aus:
Code:
@Override
public void run()
{
	while(q.isEmpty())
	{
		try
		{
			Thread.sleep(1000);
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
	}
	
	while(!q.isEmpty())
	{
		Car c = q.getCar();
		if (c != null)
		{
			c.repair(id);
		}
	}
	
	System.out.println(getName() + " quits working");
}

Nebenbei. Man kann Threads mit setName einen Namen geben. Dann sieht das auch im Debugger sehr nett aus. Es steht dann nicht immer nur "Thread [Thread-0], Thread [Thread-1]" etc.
 

BasBeg

Aktives Mitglied
@mihe7, @Oneixee5 und @X5-599 Danke für die Antworten :)

Ich hab das ganze wohl verquert getextet. JA es ging mir um die Abbruchbedingung in der run Methode des Mechanikers.
Mit Sleep könnte man das machen stimmt, aktiv warten bis etwas in der Queue ist. Danach würde das Programm die Autos einfügen und die Mechaniker Threads arbeiten die Autos ab und sind am Abend fertig und das Programm beendet 😃

An wait() und notify() dachte ich gestern Abend auch noch. Vielleicht könnte man die Threads ja erst mal alle warten lassen -> wäre zwar blöd, doch ich wollte diese Endlosschleife da raus bekommen 🤣 Das Probier ich später mal vielleicht klappt es ja. Anders nehme ich die Schläfrigen Threads 😇

___
Ich dachte an ein Observer, weil der hätte dann ja den Thread sagen können, so jetzt ist etwas in der Queue drin und ihr könnt los legen (falls so etwas geht)
 

mihe7

Top Contributor
JA es ging mir um die Abbruchbedingung in der run Methode des Mechanikers.
Genau deswegen habe ich auch gefragt, ob die leere Queue ein gutes Kriterium ist.

Das wäre sicher der Fall, wenn im Vorfeld bekannt ist, was der Mechaniker den Tag über zu tun hat. Der Inhalt der Queue steht dann bereits fest, bevor die Mechaniker die Arbeit beginnen und es gibt überhaupt kein Problem.

Wenn dagegen neue Aufträge reinkommen können, während der Mechaniker arbeitet, stellt sich natürlich die Frage: woran erkennt der Mechaniker denn, wann Feierabend ist?

Mal im real life: Vormittag kommt kein Kunde, die Arbeiten an den auf dem Hof stehenden Autos sind abgeschlossen. Hat der Mechaniker nun Feierabend? Es könnte ja auch um 14:00 Uhr der nächste Kunde kommen.

Der Mechaniker hat Feierabend, wenn Cheffe sagt, dass er nach Hause gehen kann. So etwas lässt sich z. B. mit Poison Pills simulieren: jeder Mechaniker nimmt so lange Aufträge aus der Queue, bis er einen "Feierabendauftrag" erhält.

Vielleicht könnte man die Threads ja erst mal alle warten lassen -> wäre zwar blöd, doch ich wollte diese Endlosschleife da raus bekommen 🤣
Nein, das ist nicht blöd. Thread wird schlafen gelegt, sobald etwas in der Queue liegt, wird aufgeweckt. Zusammen mit den "Feierabendaufträgen" hast Du dann eine runde Sache.
 

BasBeg

Aktives Mitglied
Das höre ich zum ersten mal. Muss ich mal schauen ob ich was dazu finde.

Nein, das ist nicht blöd. Thread wird schlafen gelegt, sobald etwas in der Queue liegt, wird aufgeweckt. Zusammen mit den "Feierabendaufträgen" hast Du dann eine runde Sache.
Darum ging es mir an sich auch. Nur kenne ich mich mit Threads noch nicht so gut aus und weiß nicht wie die sich verhalten und wie man sie "gut" steuern kann etc. o_O

Doch wir sind ja fleißig da wird es von mal zu mal besser ;)

___
Okay, das mit den Feierabendauftrag finde ich jetzt noch verzwickt. Muss ich dann jedem Mechaniker eine ID geben und den Aufträgen in meiner Queue gebe ich dann auch eine ID, also den Feierabendauftrag. Sobald die beiden IDs dann gleich sind kann der Mechaniker seine Arbeit beenden. Wie kill ich dann diesen Thread? 🤔 Das mit den IDs gefällt mir irgendwie auch nicht so ganz. 🤔
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Muss ich dann jedem Mechaniker eine ID geben
Nein, es geht nur darum, dass Du ein Objekt hast, das sich von echten Aufträge unterscheidet. Deine Aufträge sind ja Cars. Wenn wir mal dabei bleiben, könntest Du einfach einen NONE-Car definieren:
Java:
public class Car {
    private int id;
    static int i = 0;

    public static final Car NONE = new Car(-1); // EDIT: korrigiert

    private Car(int id) {
        this.id = id;
    }

    Car() {
        id = i++;
    }

    public void repair(int id) {
        System.out.println("Mechaniker " + id + ": Auto " + this.id + " wird repariert");
        try {
            Thread.sleep((int) (Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getId() {
        return id;
    }
}

Normalerweise würdest Du noch equals und hashCode überschreiben, dann könntest Du einen Car direkt mit Car.NONE vergleichen, ohne geht es halt nur über die IDs.

Dein Garage-Objekt weiß, dass es n Mechaniker gibt. Also kannst Du dort eine Methode zum Abschließen der Aufträge einbauen, die nichts anderes macht, als n-mal Car.NONE in die Queue einzufügen.

Diese Methode wird aufgerufen, nachdem alle echten Aufträge eingefügt wurden:
Java:
    public static void main(String[] args) {
        Garage g = new Garage();
        for(int i = 0; i < 120; i++)
            g.dropCar(new Car());
        g.finish(); // schickt die Mechaniker in den Feierabend.
    }

Die Schleife beim Mechaniker läuft nun einfach genau so lange, bis man auf ein Car.NONE trifft. Die run-Methode wird dadurch verlassen, womit auch der Thread beendet wird.

Beispielhafte Skizze (hier wäre getCar() ein blockierender Aufruf):
Java:
Car car = q.getCar();
while (car.getId() != Car.NONE.getId()) {
    processCar(car);
    car = q.getCar();
}

Hier den Car zu missbrauchen, ist ein klein wenig quick & dirty; aber es geht an der Stelle nur mal ums Prinzip.
 
Zuletzt bearbeitet:

BasBeg

Aktives Mitglied
Bei mir bleibt das Problem gleich!

Die Threads laufen los, schauen ob etwas in der Queue ist und sind fertig oder man bekommt null oder oder oder ....

Sobald das erste Auto in der Queue liegt müsste ich das erkennen können.
 

mihe7

Top Contributor
Die Threads laufen los, schauen ob etwas in der Queue ist und sind fertig oder man bekommt null oder oder oder ....

Sobald das erste Auto in der Queue liegt müsste ich das erkennen können.
Beim Aufruf von getCar() muss der Thread einfach warten, bis es etwas aus der Queue zu entnehmen gibt. Das lässt sich recht einfach mit Object#wait/notify (oder notifyAll) erledigen.
 

temi

Top Contributor
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Threads Jede Klasse einem Thread zuweisen Java Basics - Anfänger-Themen 7
F Threads Variable aus einem Thread in main Methode? Java Basics - Anfänger-Themen 9
S Erste Schritte Suche nach einem guten JAVA-Buch (Definition im Thread) Java Basics - Anfänger-Themen 6
A Jlayer: Wie sound stoppen der in einem Thread läuft Java Basics - Anfänger-Themen 7
K Verschiedene (Thread) Objekt-Positionen (int) in einem Array zusammenfassen Java Basics - Anfänger-Themen 3
M Warten bis Thread an einem Semaphore angekommen ist Java Basics - Anfänger-Themen 4
C Soundwiedergabe in einem Thread - Speicher besser bereinigen Java Basics - Anfänger-Themen 3
S Racecondition in einem Thread Java Basics - Anfänger-Themen 5
H Problem mit einem Programmversuch (geteilter Thread) Java Basics - Anfänger-Themen 3
M mehrer run methoden in einem Thread Java Basics - Anfänger-Themen 7
A Andere Methoden aus einem Thread starten Java Basics - Anfänger-Themen 8
K Problem beim Einbau von einem Thread in eine Gui Java Basics - Anfänger-Themen 9
W Aus einem Runnable-thread auf einen JFrame zugreifen Java Basics - Anfänger-Themen 5
B Methoden in einem Thread ausführen Java Basics - Anfänger-Themen 2
I Dateigröße von einem InputStream oder byte[] bekommen Java Basics - Anfänger-Themen 2
H Compiler-Fehler Klasse in einem Package wird nicht gefunden bzw. akzeptiert Java Basics - Anfänger-Themen 12
S Algorithmus entwicklen, der zu einem gegebenen Datum die Jahreszeit ermittelt Java Basics - Anfänger-Themen 13
A Elemente in einem Array Java Basics - Anfänger-Themen 5
G Position einer unbekannten 3-stelligen-Zahl in einem String finden Java Basics - Anfänger-Themen 15
S Eine Variable in einem Array speichern Java Basics - Anfänger-Themen 5
T Methode, die prüft ob in einem Int-Array maximal 2 Zahlen enthalten sind, die größer als ihr Vorgänger sind Java Basics - Anfänger-Themen 5
berserkerdq2 Wie gebe ich den Pfad zu einer Datei an, die in einem Ordner in Eclipse ist? Java Basics - Anfänger-Themen 1
M Objekt in einem Objekt speichern Java Basics - Anfänger-Themen 9
J Speichern von zwei Variablen durch Auslesen aus einem Numberfield Java Basics - Anfänger-Themen 2
L Gridmuster in einem Array Java Basics - Anfänger-Themen 2
D spezifische Knoten in einem Baum zählen Java Basics - Anfänger-Themen 9
X Erste Schritte Hilfe bei einem kleinen Spiel. Java Basics - Anfänger-Themen 19
O Array mit einem Zeichen vergleichen Java Basics - Anfänger-Themen 1
B Brauche Hilfe zu einem Code Java Basics - Anfänger-Themen 5
J Zahlen bis zu einem bestimmten Grenzwert ausgeben Java Basics - Anfänger-Themen 11
P9cman Vokale in einem String überprüfen mittels Rekursion Java Basics - Anfänger-Themen 8
M Wie kann ich eine Methode aus einem Interface in eine Klasse implementieren, so dass sie ihre Funktion ausführt? Java Basics - Anfänger-Themen 7
M Wie kann ich in einem Konstruktor die Methode eines anderen Interfaces mit den jeweiligen Parametern aufrufen? Java Basics - Anfänger-Themen 8
Igig1 Wie lasse ich dir Werte in einem Array zusammenrücken? Java Basics - Anfänger-Themen 4
W Methode, die mit einem Datum arbeitet? Java Basics - Anfänger-Themen 22
Igig1 Welche Werte sind als default Werte in einem Array, der als Datentyp eine Klasse hat? Java Basics - Anfänger-Themen 1
Kiki01 Wie würde eine geeignete Schleife aussehen, die die relative Häufigkeit für jeden Charakter in einem Text bestimmt? Java Basics - Anfänger-Themen 3
C Hilfe bei einem Anfängerprojekt Java Basics - Anfänger-Themen 25
U Char zu einem String machen Java Basics - Anfänger-Themen 1
U Kann man bei Java gleich mehrere Bedingungen prüfen in der If, aber in einem "Satz"? Java Basics - Anfänger-Themen 1
Schniffi Nur bestimmte Bilder aus einem Array auf Image Button anzeigen lassen Java Basics - Anfänger-Themen 3
S Längster Pfad zwischen zwei Vertices in einem Graph Java Basics - Anfänger-Themen 3
I Upload File zu einem Webservice Java Basics - Anfänger-Themen 17
Naxon89 Input/Output Ein PDF in einem BLOB umwandeln um ihn dann als PDF wieder anzuzeigen Java Basics - Anfänger-Themen 3
Kotelettklopfer Mehrere Projekte in einem Git verwalten Java Basics - Anfänger-Themen 10
B in einem Array den nächstgelegenen Wert zu einem eingabewert finden Java Basics - Anfänger-Themen 8
E JPanels auf gleicher Höhe (Y-Achse) in einem FlowLayout platzieren Java Basics - Anfänger-Themen 7
N Aus einem String die Anzahl der Vokale auslesen Java Basics - Anfänger-Themen 40
C Programm das feststellen kann, ob eine eingegebene Zahl einem Schaltjahr entspricht, richtig geschrieben? Java Basics - Anfänger-Themen 11
M Von einem Menü Methode aus anderer Klasse ausführen, die errechnete Werte in Datei schreibt. Java Basics - Anfänger-Themen 8
A Zu einem bestimmten Ort im Code springen Java Basics - Anfänger-Themen 11
I Validation, ob String ein Wert aus einem Enum enthält Java Basics - Anfänger-Themen 3
B Häufigkeit einzelner Zahlen in einem Array Java Basics - Anfänger-Themen 6
D Zufällige Auswahl aus einem angelegten Array? Java Basics - Anfänger-Themen 10
A Löschen von Leerzeichen in einem char array ohne methoden Java Basics - Anfänger-Themen 6
T Methode schreiben, die einem Array ein Stringelement hinzufügt, wenn dieses noch nicht enthalten ist. Java Basics - Anfänger-Themen 6
TimoN11 IntelliJ , Ausgabe von einem Quellcode in Eingabe eines Quellcodes Java Basics - Anfänger-Themen 1
R Mehrere Buchstaben aus einem String entfernen Java Basics - Anfänger-Themen 1
J Alle .java Dateien von einem Verzeichnis in eine Zip speichern Java Basics - Anfänger-Themen 2
J Alle Dateien aus einem Verzeichnis laden Java Basics - Anfänger-Themen 10
H Minimum in einem Array bestimmen Java Basics - Anfänger-Themen 7
J Input/Output Konstruktor ergänzen, der zur Datei mit einem Objekt passt Java Basics - Anfänger-Themen 0
P Auswahl bei einem Videoverleih limitieren Java Basics - Anfänger-Themen 4
B Quicksort in Verbindung mit einem Projekt Java Basics - Anfänger-Themen 1
P Ein Objekt nach einem String durchsuchen? Java Basics - Anfänger-Themen 7
dieter000 Frage zu einem Beispiel... Java Basics - Anfänger-Themen 5
O Java Weinachtsbaum in einem Bilderramen Java Basics - Anfänger-Themen 5
C Größte Zahl aus einem Array ermitteln(als statische Methode) Java Basics - Anfänger-Themen 31
F Java Programm, das kleine Buchstaben in einem String zählen soll und bei großen Buchstaben oder Sonderzeichen abbrechen soll. Java Basics - Anfänger-Themen 5
Y Knoten an einem gegebenen Index aus einer Liste entfernen. Java Basics - Anfänger-Themen 6
G Methoden Methode die aus einem Array ein Index ausgibt? Java Basics - Anfänger-Themen 2
J Verschieben von Buchstaben in einem String um vorgegebene Anzahl von Zeichen innerhalb eines weiteren String Java Basics - Anfänger-Themen 12
Kingamadeus2000 Anzahl der Ziffern der kürzesten Zahl aus einem zurückliefern Java Basics - Anfänger-Themen 1
U Muster in einem Array erkennen Java Basics - Anfänger-Themen 8
Y Wie greift man auf die Knoten in einem Binärbaum zu? Java Basics - Anfänger-Themen 5
rafi072001 Lesen aus einem Excel File Java Basics - Anfänger-Themen 10
Y Wie kann man überprüfen, ob bei einem Print Befehl tatsächlich etwas geprintet wurde? Java Basics - Anfänger-Themen 4
J Lösungen zu einem Lückentext finden Java Basics - Anfänger-Themen 0
Z Char Array an zufälligen stellen mit einem "x" füllen. Java Basics - Anfänger-Themen 4
L Alle Ziele in einem Raster abknallen Java Basics - Anfänger-Themen 17
T Auf einem Schachbrett bewegen programmieren Java Basics - Anfänger-Themen 2
F JMenuItem Kann nicht nach einem String benannt werden... Java Basics - Anfänger-Themen 11
H 3 Comparatoren zu einem zusammenfassen - Chaining... Java Basics - Anfänger-Themen 15
N LocalTime einem Objekt zuweisen Java Basics - Anfänger-Themen 2
B Berechnung der Position von Kinderelemente von einem Elternknoten Java Basics - Anfänger-Themen 23
N Länge eines Arrays in einem Objekt testen Java Basics - Anfänger-Themen 51
B Alle Links in einem Text suchen und ersetzen mit einem neuen Link Java Basics - Anfänger-Themen 18
J Elemente in einem 2D-Array summieren Java Basics - Anfänger-Themen 6
J String aus einem Array entfernen Java Basics - Anfänger-Themen 10
L Breadth-First Search statt einem Pfad, alle Pfade herausfinden Java Basics - Anfänger-Themen 4
L Wie frage ich ab, ob in einem Array, Werte doppelt vorkommen? Java Basics - Anfänger-Themen 4
J Ich brauche Hilfe bei einem Code (Variablen speichern) Java Basics - Anfänger-Themen 29
P Arraylist zu einem Array bringen mit Verschachtelung Java Basics - Anfänger-Themen 11
S Ersetzen eines Asterix in einem String Java Basics - Anfänger-Themen 8
X Nach einem Bruch testen ob es eine ganze Zahl ist Java Basics - Anfänger-Themen 6
M Von einem JTextField Doublewerte entgegennehmen Java Basics - Anfänger-Themen 2
M Ist es möglich, das größte und zweitgrößte element in einem Array mit nur einer Schleife ausfindig zu machen ? Java Basics - Anfänger-Themen 19
H Objekt aus einem Array löschen Java Basics - Anfänger-Themen 1
F Aufgabe: Abstand von einem Punkt zu einem anderen Punkt Java Basics - Anfänger-Themen 10
H Befehle in einem Menü aktivieren Java Basics - Anfänger-Themen 1

Ähnliche Java Themen


Oben