„Hallo Amigo! Ellie hat dir von Threads erzählt, und ich werde dir erklären, wie du damit arbeitest. Wenn du einen neuen Thread erstellen willst, musst du:“

1) Ein Thread-Objekt erstellen

2) Dieses der Methode übergeben, die du ausführen möchtest

3) Die start-Methode mit dem erstellten Thread-Objekt aufrufen

Betrachte dieses Beispiel:

Code Beschreibung
class Printer implements Runnable
{
public void run()
{
System.out.println("I’m printer");
}
}
Klasse, die das Runnable-Interface implementiert.
public static void main(String[] args)
{
Printer printer = new Printer();
Thread childThread = new Thread(printer);
childThread.start();
}
1 Erzeuge eine Instanz der Printer-Klasse, welche die run-Methode implementiert.
2 Erstelle ein neues Thread-Objekt. Wir übergeben dem Konstruktor das Printer-Objekt, dessen run()-Methode aufgerufen werden muss.
3 Starte den neuen Thread durch den Aufruf der start()-Methode.

Kleine Java-Programme bestehen in der Regel aus einem Thread, dem ‚Haupt-Thread‘. Aber Programme starten häufiger zusätzliche Threads, die ‚untergeordnete Threads‘ genannt werden. Der Haupt-Thread führt die main-Methode aus und wird dann beendet. Die run-Methode von Runnable ist die analoge Methode für untergeordnete Threads.

„Ah, viele Threads bedeuten viele main-Methoden.“

Neue Threads erstellen und starten - 1

Um einem Thread-Objekt mitzuteilen, welche spezifische Methode es starten soll, müssen wir ihm irgendwie eine Methode übergeben. In Java geschieht dies über das Runnable-Interface. Dieses Interface enthält eine einzige abstrakte Methode: void run(). Die Thread-Klasse hat den Konstruktor Thread(Runnable Runnable). Du kannst jedes Objekt übergeben, welches das Runnable-Interface implementiert.

Deine Klasse muss von Runnable erben und dessen run-Methode überschreiben. Der Aufruf dieser Methode startet den neuen Thread. In der run-Methode kannst du schreiben, was du willst.

Code Beschreibung
class Printer implements Runnable
{
private String name;
public Printer(String name)
{
this.name = name;
}
public void run()
{
System.out.println("I’m " + this.name);
}
}
Klasse, die das Runnable-Interface implementiert.
public static void main(String[] args)
{
Printer printer1 = new Printer("Nick");
Thread thread1 = new Thread(printer1);
thread1.start();

Printer printer2 = new Printer("Jack");
Thread thread2 = new Thread(printer2);
thread2.start();
}
Erstelle zwei Threads, von denen jeder auf einem eigenen Printer-Objekt basiert.
public static void main(String[] args)
{
Printer printer = new Printer("Natasha");

Thread thread1 = new Thread(printer);
thread1.start();

Thread thread2 = new Thread(printer);
thread2.start();

Thread thread3 = new Thread(printer);
thread3.start();
}
Erstelle drei Threads basierend auf einem einzigen Printer-Objekt.

Außerdem kannst du das alles in einer Klasse kombinieren. Die Thread-Klasse erbt vom Runnable-Interface, also musst du nur dessen run-Methode überschreiben:

Noch eine Möglichkeit, einen neuen Thread zu erstellen
class Printer extends Thread
{
private String name;
public Printer(String name)
{
this.name = name;
}
public void run()
{
System.out.println("I’m " + this.name);
}
}
Erbe von der Thread-Klasse, die das Runnable-Interface implementiert, und überschreibe dann die run-Methode.
public static void main(String[] args)
{
Printer printer = new Printer("Jack");
printer.start();

Printer printer2 = new Printer("Jack");
printer2.start();

}
Erstelle zwei Threads, von denen jeder auf einem eigenen Printer-Objekt basiert.

„Das ist eine elegantere Lösung.“

„Ja, aber sie hat ihre Schwächen:“

1) Man muss eventuell mehrere Threads auf der Grundlage eines einzigen Objekts starten, so wie im Beispiel mit Natasha.

2) Wenn du von der Thread-Klasse erbst, kannst du keine weitere Elternklasse zu deiner Klasse hinzufügen.

3) Wenn deine Klasse eine Elternklasse hat, kannst du keinen Thread als zweite Elternklasse hinzufügen.

„Mit anderen Worten, nachdem die start-Methode aufgerufen wurde, beginnt jeder der Threads mit der Ausführung der run-Methode des an den Konstruktor übergebenen Objekts?“

„Ja. Wenn nichts an den Konstruktor übergeben wird, dann führt der Thread einfach seine interne run-Methode aus.“

„Aber warum rufen wir die Methode nicht einfach so auf?“

Code
public static void main(String[] args)
{
 Printer printer1 = new Printer("Nick");
 printer1.run();
}

„Wenn der Haupt-Thread die run-Methode erreicht, geht der ‚kleiner Roboter‘ einfach hinein und führt alle Befehle darin aus. Erst nach deren Ausführung kehrt er zur main-Methode zurück und fährt mit der Ausführung weiterer Befehle fort. Es wird also kein zweiter ‚kleiner Roboter‘ erstellt. Alle Arbeiten werden sequentiell (nacheinander) und nicht parallel (gleichzeitig) ausgeführt.“

„Alles klar. Kann man denn eine andere Methode aufrufen, eine andere als run?“

„Nein. Es ist alles an das Runnable-Interface gebunden, das nur eine seiner Methoden ‚kennt‘: run().“