Java verfügt über einen speziellen Thread, den Daemon-Thread, der eine sehr niedrige Priorität hat und nur ausgeführt wird, wenn andere Threads im selben Programm nicht ausgeführt werden.
Da Daemon-Threads über diese Eigenschaften verfügen, werden sie im Allgemeinen zur Bereitstellung von Diensten für normale Threads (auch Benutzer-Threads genannt) im Programm verwendet. Sie haben im Allgemeinen eine Endlosschleife oder werden zum Warten auf Anforderungsdienste oder zum Ausführen von Aufgaben usw. verwendet. Sie können keine wichtige Arbeit leisten, da wir nicht sicher sind, wann ihnen CPU-Zeit zugewiesen wird, und sie werden automatisch beendet, wenn keine anderen Threads ausgeführt werden. Eine typische Anwendung dieses Thread-Typs ist die Java-Garbage-Collection.
Im Beispiel in diesem Abschnitt erstellen wir zwei Threads, einen ist ein normaler Thread, der Ereignisse in die Warteschlange schreibt, der andere ist ein Daemon-Thread, der Ereignisse in der Warteschlange löscht und Ereignisse löscht, die länger als 10 Sekunden vorhanden sind.
weiß es
Führen Sie die folgenden Schritte aus, um das Beispielprogramm zu implementieren.
1. Erstellen Sie eine Event-Klasse, die nur zum Speichern von Ereignisinformationen verwendet wird, die für die Programmausführung erforderlich sind. Deklarieren Sie zwei Eigenschaften, eine ist die Datumseigenschaft vom Typ java.util.Date und die andere ist die Ereigniseigenschaft vom Typ String. Generieren Sie dann die Lese- und Schreibmethoden für diese beiden Eigenschaften. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
öffentliches Klassenereignis {
privates Datum Datum;
privates String-Ereignis;
öffentliches Datum getDate() {
Rückgabedatum;
}
public void setDate(Datum date) {
this.date = date;
}
öffentlicher String getEvent() {
Rückkehrereignis;
}
public void setEvent(String event) {
this.event = Ereignis;
}
}
2. Erstellen Sie eine Klasse mit dem Namen WriterTask und implementieren Sie die Runnable-Schnittstelle. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
Die öffentliche Klasse WriterTask implementiert Runnable {
3. Deklarieren Sie ein Warteschlangenattribut zum Speichern von Ereignissen, implementieren Sie den Konstruktor der Klasse und verwenden Sie seine Parameter, um das Warteschlangenattribut zu initialisieren. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
private Deque<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
4. Implementieren Sie die run()-Methode dieser Aufgabe, die eine Schleife enthält, die 100 Mal durchlaufen wird. Bei jedem Durchlauf wird ein neues Ereignisobjekt erstellt, dann in der Warteschlange gespeichert und schläft eine Sekunde lang. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Ereignisereignis = neues Ereignis();
event.setDate(new Date());
event.setEvent(String.format("Der Thread %s hat ein Ereignis generiert",
Thread.currentThread().getId()));
deque.addFirst(event);
versuchen {
TimeUnit.SECONDS.sleep(1);
} Catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5. Erstellen Sie eine Klasse mit dem Namen CleanerTask und erben Sie die Thread-Klasse. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse CleanerTask erweitert Thread {
6. Deklarieren Sie ein Warteschlangenattribut zum Speichern von Ereignissen, implementieren Sie den Konstruktor der Klasse und verwenden Sie seine Parameter, um das Warteschlangenattribut zu initialisieren. Legen Sie in der Konstruktionsmethode den Thread als Daemon-Thread fest, indem Sie die Methode setDaemon() aufrufen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(true);
}
7. Implementieren Sie die Methode run(). Es gibt eine Endlosschleife im Methodenkörper, um die aktuelle Zeit zu ermitteln und dann die Methode clearn() aufzurufen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
@Override
public void run() {
while (wahr) {
Datum date = neues Date();
sauber(Datum);
}
}
8. Implementieren Sie in dieser Methode die letzte Zeit und überprüfen Sie dann den Zeitunterschied zwischen der Zeit und der aktuellen Zeit. Wenn sie vor 10 Sekunden erstellt wurde, löschen Sie das aktuelle Ereignis und überprüfen Sie dann das nächste Ereignis. Wenn ein Ereignis gelöscht wird, werden die Informationen über das gelöschte Ereignis und die letzte Länge der Warteschlange ebenfalls ausgedruckt, sodass der Ausführungsfortschritt des Programms beobachtet werden kann. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
private Leere sauber(Datum Datum) {
langer Unterschied;
boolean delete;
if (deque.size() == 0) {
zurückkehren;
}
delete = false;
Tun {
Ereignis e = deque.getLast();
Differenz = date.getTime() - e.getDate().getTime();
if (Differenz > 10000) {
System.out.printf("Cleaner: %s/n", e.getDate());
deque.removeLast();
delete = true;
}
} while (Differenz > 10000);
if (löschen) {
System.out.printf("Clearner: Größe der Warteschlange: %d/n", deque.size());
}
}
9. Erstellen Sie die Hauptklasse des Programms, die Main-Klasse, und implementieren Sie dann die main()-Methode. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse Main {
public static void main(String[] args) {
10. Verwenden Sie die Deque-Klasse, um eine Warteschlange zum Speichern von Ereignissen zu erstellen. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
Deque<Event> deque = new ArrayDeque<>();
11. Erstellen und starten Sie drei WriterTask-Threads und einen CleanerTask-Thread. Der Code lautet wie folgt:
Kopieren Sie den Codecode wie folgt:
Deque<Event> deque = new ArrayDeque<>();
WriterTaskwriter = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
Thread thread = neuer Thread(Writer);
thread.start();
}
CleanerTask Cleaner = new CleanerTask(deque);
Cleaner.start();
12. Führen Sie das Programm aus und sehen Sie sich die Ausführungsergebnisse an.
weiß warum
Wenn wir die Ausführungsergebnisse des Programms analysieren, können wir sehen, dass die Warteschlange zunächst auf 30 ansteigt und sich dann zwischen 27 und 30 ändert, bis die Programmausführung endet.
Das Programm beginnt zunächst mit der Ausführung von drei WriterTask-Threads. Jeder Thread fügt zunächst ein Ereignis zur Warteschlange hinzu und schläft dann eine Sekunde lang. Nach Ablauf der ersten 10 Sekunden befinden sich dreißig Ereignisse in der Warteschlange. Während dieser 10 Sekunden, wenn alle drei WriterTask-Threads ruhen, wird auch der CleanerTask-Thread ausgeführt, es werden jedoch keine Ereignisse gelöscht, da die Generierungszeit aller Ereignisse 10 Sekunden nicht überschreitet. Nach den ersten 10 Sekunden fügen drei WriterTasks jede Sekunde drei Ereignisse zur Warteschlange hinzu. Ebenso löscht CleanerTask jede Sekunde drei Ereignisse. Die Zahl der Veranstaltungen schwankt also zwischen 27 und 30.
Wenn sich alle WriterTask-Threads im Ruhezustand befinden, können wir die Zeit frei verarbeiten, sodass der Daemon-Thread während dieser Zeit ausgeführt werden kann. Wenn Sie die Ruhezeit des WriterTask-Threads kürzer festlegen, erhält der CleanerTask-Thread weniger CPU-Laufzeit. Wenn dies der Fall ist, wird die Länge der Warteschlange weiter wachsen, da der CleanerTask-Thread nie genug Laufzeit erhält, um genügend Ereignisse zu löschen.
niemals enden
Der Thread kann nur als Daemon-Thread festgelegt werden, indem die Methode setDaemon() vor dem Aufruf der Methode start() aufgerufen wird. Sobald ein Thread ausgeführt wird, kann der Daemon-Status nicht mehr geändert werden.
Sie können isDaemon() auch verwenden, um zu überprüfen, ob ein Thread ein Daemon-Thread ist. Wenn es sich um einen Daemon-Thread handelt, gibt er „true“ zurück; wenn es sich um einen gewöhnlichen Thread handelt, gibt er „false“ zurück.
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
Vollständige Versionen des gesamten in diesem Abschnitt verwendeten Beispielcodes.
Vollständiger Code der Event-Klasse
Kopieren Sie den Codecode wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
/**
*Veranstaltungsinformationsklasse
* Datum: 19.09.2013
* Zeit: 22:56
*/
öffentliches Klassenereignis {
privates Datum Datum;
privates String-Ereignis;
öffentliches Datum getDate() {
Rückgabedatum;
}
public void setDate(Datum date) {
this.date = Datum;
}
öffentlicher String getEvent() {
Rückkehrereignis;
}
public void setEvent(String event) {
this.event = Ereignis;
}
}
Vollständiger Code der WriterTask-Klasse
Kopieren Sie den Codecode wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
/**
* Generieren Sie jede Sekunde ein Ereignis.
* Datum: 19.09.2013
* Zeit: 22:59
*/
Die öffentliche Klasse WriterTask implementiert Runnable {
private Deque<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Ereignisereignis = neues Ereignis();
event.setDate(new Date());
event.setEvent(String.format("Der Thread %s hat ein Ereignis generiert",
Thread.currentThread().getId()));
deque.addFirst(event);
versuchen {
TimeUnit.SECONDS.sleep(1);
} Catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Vollständiger Code der CleanerTask-Klasse
Kopieren Sie den Codecode wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
import java.util.Deque;
/**
* Ereignisbereinigung
* Datum: 19.09.2013
* Zeit: 23:33
*/
öffentliche Klasse CleanerTask erweitert Thread {
private Deque<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(true);
}
@Override
public void run() {
while (wahr) {
Datum date = neues Date();
sauber(Datum);
}
}
/**
* Veranstaltung löschen.
*
* @param Datum
*/
private Leere sauber(Datum Datum) {
langer Unterschied;
boolean delete;
if (deque.size() == 0) {
zurückkehren;
}
delete = false;
Tun {
Ereignis e = deque.getLast();
Differenz = date.getTime() - e.getDate().getTime();
if (Differenz > 10000) {
System.out.printf("Cleaner: %s/n", e.getDate());
deque.removeLast();
delete = true;
}
} while (Differenz > 10000);
if (löschen) {
System.out.printf("Clearner: Größe der Warteschlange: %d/n", deque.size());
}
}
}
Der vollständige Code der Hauptklasse
Kopieren Sie den Codecode wie folgt:
Paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Datum: 19.09.2013
* Zeit: 23:54
*/
öffentliche Klasse Main {
public static void main(String[] args) {
Deque<Event> deque = new ArrayDeque<>();
WriterTaskwriter = new WriterTask(deque);
for (int i = 0; i < 3; i++) {
Thread thread = neuer Thread(Writer);
thread.start();
}
CleanerTask Cleaner = new CleanerTask(deque);
Cleaner.start();
}
}