Das Gruppieren von Threads ist eine interessante Funktion der Java-Parallelitäts-API. Wir können eine Gruppe von Threads als unabhängige Einheit behandeln und die Thread-Objekte in der Thread-Gruppe nach Belieben manipulieren. Sie können beispielsweise eine Gruppe von Threads so steuern, dass sie dieselbe Aufgabe ausführen, ohne sich darum zu kümmern, wie viele Threads noch ausgeführt werden, und Sie können auch einen Interrupt-Aufruf verwenden, um die Ausführung aller Threads zu unterbrechen.
Java stellt die ThreadGroup-Klasse zur Steuerung einer Thread-Gruppe bereit. Eine Thread-Gruppe kann über ein Thread-Objekt oder von anderen Thread-Gruppen erstellt werden, um eine Baumstruktur von Threads zu generieren.
Laut „Effective Java“ wird die Verwendung von ThreadGroup nicht mehr empfohlen. Es wird empfohlen, Executor zu verwenden.
——D Guagot erklärt das.
In diesem Abschnitt verwenden wir ThreadGroup, um ein einfaches Beispiel zu entwickeln. Wir werden zehn Threads mit unterschiedlichen Ruhezeiten erstellen (z. B. die Simulation einer Suche) und den Rest unterbrechen, wenn einer davon abgeschlossen ist.
weiß es
Befolgen Sie die unten gezeigten Schritte, um den Beispielcode zu vervollständigen.
1. Erstellen Sie eine Klasse mit dem Namen „Result“, um den Namen des ersten Threads zu speichern, der die Aufgabe abschließt. Deklarieren Sie eine private Variable vom Typ String, benennen Sie sie und generieren Sie Setter/Getter-Methoden. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
öffentliches Klassenergebnis {
privater String-Name;
öffentlicher String getName() {
Rückgabename;
}
public void setName(String name) {
this.name = Name;
}
}
2. Erstellen Sie eine Klasse mit dem Namen SearchTask und implementieren Sie die Runnable-Schnittstelle. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
Die öffentliche Klasse SearchTask implementiert Runnable {
3. Deklarieren Sie eine private Variable vom Typ Ergebnis und instanziieren Sie die Variable über den Konstruktor. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
privates Ergebnis result;
public SearchTask(Ergebnisergebnis) {
this.result = Ergebnis;
}
4. Implementieren Sie die Methode run() und rufen Sie darin die Methode doTask() auf, um auf den Abschluss oder die Unterbrechung zu warten. Diese Methode gibt auch Informationen an die Konsole aus, um den Start, das Ende oder die Unterbrechung des Threads anzuzeigen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
@Override
public void run() {
Stringname = Thread.currentThread().getName();
System.out.printf("Thread %s: Start/n", name);
versuchen {
doTask();
result.setName(name);
} Catch (InterruptedException e) {
System.out.printf("Thread %s: Unterbrochen/n", name);
zurückkehren;
}
System.out.printf("Thread %s: End/n", name);
}
5. Implementieren Sie die Methode doTask(), die ein Random-Objekt erstellt und das Objekt dann verwendet, um eine Zufallszahl zu generieren, um die Thread-Ruhezeit anzupassen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
// Suche simulieren
private void doTask() wirft InterruptedException {
Zufällig random = new Random(new Date().getTime());
int value = (int) (random.nextDouble() * 100);
System.out.printf("Thread %s: %d/n",
Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
6. Erstellen Sie die Hauptklasse des Beispielprogramms, Main, und implementieren Sie die Methode main(). Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse Main {
public static void main(String[] args) {
7. Erstellen Sie ein ThreadGroup-Objekt mit dem Namen Searcher. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
ThreadGroup threadGroup = new ThreadGroup("Searcher");
8. Erstellen Sie dann ein Result-Objekt und ein SearchTask-Objekt. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
Ergebnis result = new Result();
SearchTask searchTask = new SearchTask(result);
9. Erstellen Sie mit dem SearchTask-Objekt zehn Thread-Objekte. Übergeben Sie beim Erstellen eines Thread-Objekts das ThreadGroup-Objekt als ersten Parameter an den Konstruktor der Thread-Klasse. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(threadGroup, searchTask);
thread.start();
versuchen {
TimeUnit.SECONDS.sleep(1);
} Catch (InterruptedException e) {
e.printStackTrace();
}
}
10. Verwenden Sie die Methode list(), um die Informationen des ThreadGroup-Objekts auszudrucken. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
System.out.printf("Anzahl der Threads: %d/n", threadGroup.activeCount());
System.out.println("Informationen zur Thread-Gruppe");
threadGroup.list();
11. Verwenden Sie activeCount() und enumerate(), um die Anzahl der aktiven Threads im ThreadGroup-Objekt abzurufen und in ein Thread-Array zu kopieren. Verwenden Sie die Methode get*(), um den Namen und Status des Threads abzurufen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s/n", threads[i].getName(),
threads[i].getState());
}
12. Rufen Sie die Methode waitFinish() auf und warten Sie, bis einer der Threads im ThreadGroup-Objekt die Aufgabe abgeschlossen hat. Implementieren Sie diese Methode später. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
waitFinish(threadGroup);
13. Verwenden Sie die Methode interrupt(), um andere Threads in der Thread-Gruppe zu unterbrechen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
threadGroup.interrupt();
14. Implementieren Sie die Methode waitFinish() und verwenden Sie die Methode activeCount(), um die Ausführungsergebnisse des Threads zu steuern. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
// Warten, bis die Aufgabe abgeschlossen ist
private static void waitFinish(ThreadGroup threadGroup) {
while (threadGroup.activeCount() > 9) {
versuchen {
TimeUnit.SECONDS.sleep(1);
} Catch (InterruptedException e) {
e.printStackTrace();
}
}
}
15. Führen Sie das Programm aus und überprüfen Sie den Ausführungseffekt.
weiß warum
Nachfolgend finden Sie das Ergebnis der Programmausführung. Sie sehen die Ausgabe der list()-Methode, den Status jedes Threads usw.
Kopieren Sie den Codecode wie folgt:
Thread Thread-0: Start
Thread Thread-0: 52
Thread Thread-1: Start
Thread Thread-1: 41
Thread Thread-2: Start
Thread Thread-2: 69
Thread Thread-3: Start
Thread Thread-3: 60
Thread Thread-4: Start
Thread Thread-4: 88
Anzahl der Threads: 5
Informationen zur Thread-Gruppe
java.lang.ThreadGroup[name=Sucher,maxpri=10]
Thread[Thread-0,5,Sucher]
Thread[Thread-1,5,Sucher]
Thread[Thread-2,5,Sucher]
Thread[Thread-3,5,Sucher]
Thread[Thread-4,5,Sucher]
Thread Thread-0: TIMED_WAITING
Thread Thread-1: TIMED_WAITING
Thread Thread-2: TIMED_WAITING
Thread Thread-3: TIMED_WAITING
Thread Thread-4: TIMED_WAITING
Thread Thread-1: Unterbrochen
Thread Thread-4: Unterbrochen
Thread Thread-2: Unterbrochen
Thread Thread-0: Unterbrochen
Thread Thread-3: Unterbrochen
Die ThreadGroup-Klasse speichert viele Thread-Objekte und zugehörige ThreadGroup-Objekte. Sie können auf Thread-Informationen zugreifen, indem Sie Methoden dieser Klasse aufrufen, und Sie können auch verschiedene Vorgänge darauf ausführen, z. B. Interrupts.
niemals enden
Die ThreadGroup-Klasse verfügt auch über viele Methoden. Bitte lesen Sie die API-Dokumentation für vollständige Methodenbeschreibungen.
Nutzen Sie die Lehre
Dieser Artikel wurde aus dem „Java 7 Concurrency Cookbook“ übersetzt (D Gua Ge hat ihn als „Java7 Concurrency Beispielsammlung“ gestohlen) und dient nur als Lernmaterial. Es darf ohne Genehmigung nicht für kommerzielle Zwecke verwendet werden.
Kleiner Erfolg
Nachfolgend finden Sie die vollständige Version des Codes, der in den Beispielen in diesem Abschnitt verwendet wird.
Vollständiger Code der Ergebnisklasse:
Kopieren Sie den Codecode wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe10;
/**
* Abfrageergebnisse speichern
* Datum: 30.09.2013
* Zeit: 00:45
*/
öffentliches Klassenergebnis {
privater String-Name;
öffentlicher String getName() {
Rückgabename;
}
public void setName(String name) {
this.name = Name;
}
}
Der vollständige Code der SearchTask-Klasse lautet wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe10;
import java.util.Date;
java.util.Random importieren;
import java.util.concurrent.TimeUnit;
/**
* Simulationssuchklasse
* Datum: 02.10.2013
* Zeit: 22:38
*/
Die öffentliche Klasse SearchTask implementiert Runnable {
privates Ergebnis Ergebnis;
public SearchTask(Ergebnisergebnis) {
this.result = Ergebnis;
}
@Override
public void run() {
Stringname = Thread.currentThread().getName();
System.out.printf("Thread %s: Start/n", name);
versuchen {
doTask();
result.setName(name);
} Catch (InterruptedException e) {
System.out.printf("Thread %s: Unterbrochen/n", name);
zurückkehren;
}
System.out.printf("Thread %s: End/n", name);
}
// Suche simulieren
private void doTask() wirft InterruptedException {
Zufällig random = new Random(new Date().getTime());
int value = (int) (random.nextDouble() * 100);
System.out.printf("Thread %s: %d/n",
Thread.currentThread().getName(), value);
TimeUnit.SECONDS.sleep(value);
}
}
Der vollständige Code der Main-Klasse:
Kopieren Sie den Codecode wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe10;
import java.util.concurrent.TimeUnit;
/**
* Thread-Gruppen-Beispielhauptklasse
* Datum: 02.10.2013
* Zeit: 22:45
*/
öffentliche Klasse Main {
public static void main(String[] args) {
ThreadGroup threadGroup = new ThreadGroup("Searcher");
Ergebnis result = new Result();
SearchTask searchTask = new SearchTask(result);
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(threadGroup, searchTask);
thread.start();
versuchen {
TimeUnit.SECONDS.sleep(1);
} Catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Anzahl der Threads: %d/n", threadGroup.activeCount());
System.out.println("Informationen zur Thread-Gruppe");
threadGroup.list();
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("Thread %s: %s/n", threads[i].getName(),
threads[i].getState());
}
waitFinish(threadGroup);
threadGroup.interrupt();
}
// Warten, bis die Aufgabe abgeschlossen ist
private static void waitFinish(ThreadGroup threadGroup) {
while (threadGroup.activeCount() > 9) {
versuchen {
TimeUnit.SECONDS.sleep(1);
} Catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}