Threads Alphabet

wu99

Mitglied
Hallo zusammen, ich könnte etwas Unterstützung bei meinem Programm gebrauchen. Momentan greifen die fünf erstellten Threads nacheinander zu und geben das Alphabet aus.
Ich möchte aber dass das Alphabet nur einem ausgegeben wird und die Thread synchron darauf zugreifen. Wie genau bekommen ich das am besten hin? (Also bei einer Abarbeitung des Alphabets sollen alle fünf Threads beteiligt sein)


1643302547774.png

1643302574464.png
 
Ich interpretire die Aufgabe einmal so:

Es gibt Aufgaben, die anliegen und schwer zu erfüllen sind (dies ist dein Alphabet).
Deshalb teilen sich mehrere Threads die Arbeit (das Ausgeben eines Buchstabens).

Du benötigst deshalb eine (Instanz einer) Klasse, die die Aufbaben (das Alphabet) verwaltet, und beispielsweise in einer Methode getNext() die nächste Aufgabe (den nächsten Buchstbaen) zurückgibt (und etwas wie null (oder 0) zurückgibt, wenn nichts mehr zu tun ist).
Eine weitere Klasse (extends Thread) kennt diesen "Aufgabenverwalter" (bekommt ihn im Kostruktor übergeben) und holt sich von ihm die nächste Aufgabe und bearbeitet diese Aufgabe. In deinem Fall heißt das schlicht, dass sie sich den nächsten Buchstaben holt und diesen ausgibt.
 
Du darfst nicht über "alphabet" synchronisieren, das ändert sich ja immer.

Synchronisiere über: public static final Object obj = new Object();.
 
Was soll denn synchronisiert werden?

Wenn ich einfach die Buchstaben des Alphabets in richtiger Reihenfolge ausgeben will, genügt ein:
Java:
public class Main {
    public static void main(String[] args) {
        for (char c = 'A'; c <= 'Z'; c++) {
            System.out.println(c);
        }
    }
}
Dann benötige ich keine Threads.

Wenn jedoch die Dateien A.txt bis Z.txt kopiert werden sollen (wobei die Dateien untersciedliche Größe haben können), ist es sinnlos, dass ein Thread mit dem Kopieren der Datei B.txt erst beginnt, wenn die Datei A.txt vollständig kopiert wurde. Hier macht also Synchronisation keinen Sinn.
 
Was soll denn synchronisiert werden?

Wenn ich einfach die Buchstaben des Alphabets in richtiger Reihenfolge ausgeben will, genügt ein:
Java:
public class Main {
    public static void main(String[] args) {
        for (char c = 'A'; c <= 'Z'; c++) {
            System.out.println(c);
        }
    }
}
Dann benötige ich keine Threads.

Wenn jedoch die Dateien A.txt bis Z.txt kopiert werden sollen (wobei die Dateien untersciedliche Größe haben können), ist es sinnlos, dass ein Thread mit dem Kopieren der Datei B.txt erst beginnt, wenn die Datei A.txt vollständig kopiert wurde. Hier macht also Synchronisation keinen Sinn.
Fünf Threads sollen sich den Zugriff teilen (synchron starten) und das Alphabet (von A -Z) nur einmal runter sagen.
Ich bekomm den Synchronzugriff leider nicht hin ..
Bei mir wird das Alphabet IMMER fünf mal ausgegeben ..
 
Ich habe es so implementiert (natürlich nur in Auszügen, um dir den Spaß nicht zu nehmen):

Java:
public class Main {
    public static void main(String[] args) {
        Alphabet alphabet = new Alphabet('A', 'Z');
        for (int i = 1; i <= 5; ++i) {
            CharOutput charOutput = new CharOutput(alphabet);
            charOutput.start();
        }
    }
}

class Alphabet {
    // ...
    public char getNext() {
        // ...
    }
}

class CharOutput extends Thread {
    // ...
    public void run() {
        // ...
    }
}

Zeige doch einmal, was du probiert hast - dann können wir dir besser helfen.
 
Ich habe es so implementiert (natürlich nur in Auszügen, um dir den Spaß nicht zu nehmen):

Java:
public class Main {
    public static void main(String[] args) {
        Alphabet alphabet = new Alphabet('A', 'Z');
        for (int i = 1; i <= 5; ++i) {
            CharOutput charOutput = new CharOutput(alphabet);
            charOutput.start();
        }
    }
}

class Alphabet {
    // ...
    public char getNext() {
        // ...
    }
}

class CharOutput extends Thread {
    // ...
    public void run() {
        // ...
    }
}

Zeige doch einmal, was du probiert hast - dann können wir dir besser helfen.
Okey schonmal vielen Dank ! 🙂
 
Ich habe es so implementiert (natürlich nur in Auszügen, um dir den Spaß nicht zu nehmen):

Java:
public class Main {
    public static void main(String[] args) {
        Alphabet alphabet = new Alphabet('A', 'Z');
        for (int i = 1; i <= 5; ++i) {
            CharOutput charOutput = new CharOutput(alphabet);
            charOutput.start();
        }
    }
}

class Alphabet {
    // ...
    public char getNext() {
        // ...
    }
}

class CharOutput extends Thread {
    // ...
    public void run() {
        // ...
    }
}

Zeige doch einmal, was du probiert hast - dann können wir dir besser helfen.
1643318980905.png

ich hätte es so probiert aber vergeblich ..
 
Schaffst du es denn, eine Klase Alphabet zu schreiben, dass folgender Code
Java:
public class Main {
    public static void main(String[] args) {
        Alphabet alphabet = new Alphabet('A', 'Z');
        System.out.println(alphabet.getNext());
        System.out.println(alphabet.getNext());
        System.out.println(alphabet.getNext());
    }
}
folgendes ausgibt:
Code:
A
B
C

Das wäre doch erst einmal eine begrenzte Aufgabe.
 
Weil du deinen Code leider nur als Bild veröffentlichst, kann ich ihn leider nicht ausprobieren.
Ich frage mich aber, ob der Code wirklich parallel in 4 Threads läuft; ist es wiklich eine gute Idee, die Tthreads durch ein static Objcect o zu synchronisieren?
 
Der Code entspricht auch nicht der Anforderung. Es gibt jeder Thread sein eigenes Alphabet aus, es sollten doch aber alle Threads an der Ausgabe eines Alphabets beteiligt sein. So ist die umgesetzte Synchronisierung überflüssig, wie auch die zusätzliche Exit-Bedingung.
 
@wu99 Mach das bitte so:

Java:
public class MyThread extends Thread {
    private static final Object my_lock = new Object();
    private static char nextChar = 'a';
    private static char endChar = 'z';

    @Override
    public void run() {
        boolean shouldContinue = true;
        while (shouldContinue) {
            synchronized (my_lock) {
                if (nextChar <= endChar) {
                    System.out.println(nextChar + " " + this);
                    nextChar++;
                } else {
                    shouldContinue = false;
                }
            }

            // We force switching the threads:
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) throws InterruptedException {
        int cores = Runtime.getRuntime().availableProcessors();
        MyThread[] threads = new MyThread[cores];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new MyThread();
        }
        for (MyThread t : threads) {
            t.start();
        }
        for (MyThread t : threads) {
            t.join();
        }
        System.out.println("fertig");
    }
}

MyThread gibt das Alphabet aus. Thread.sleep habe ich jetzt hinzugefügt, damit die Threads auch mal wechseln.

OHNE Synchronisierung gäbe das Chaos...

Lg 🙂
 
Jetzt bin ich aber nicht ganz so sattelfest, ob sich die einzelnen Threads nicht eine Kopie von nextChar anlegen Könnten, die nicht immer synchronisiert würde... Um das zu vermeiden, könnte man sie noch volatile-deklarieren. Aber bei mir trat das Phänomen bisher nie auf...

Aber mal ganz unabhängig davon, mehrere Threads verlangsamen bei dieser konkreten Aufgabenstellung eher die Ausführungszeit, anstatt diese zu beschleunigen. Das liegt glaube ich daran, dass die Ausgabe sequenziell erfolgen muss, sprich die Senke einen nicht parallelen Eingang hat. Außerdem sind die einzelnen Berechnungen (nextChar++;) eher nicht so aufwändig, als dass sie parallelisiert werden müssten.

Aber das Prinzip ist hoffentlich verständlich geworden. 🙂
 
Ach ja, und im Produktivcode rechnet man für gewönhlich cores-1, damit ein Core/Thread sich nur um das Scheduling kümmern kann. 🙂 Aber um das Prinzip verständlich zu machen, habe ich diesen "Overhead" einfach weggelassen in diesem Beispiel.
 

Zurück
Oben