Ich möchte ein Objekt, das einen Daemon-Thread erzeugt, der während der gesamten Lebensdauer des Prozesses ausgeführt wird. Nehmen wir nur an, es handelt sich um einen Thread in einem eingebetteten System, der darauf wartet, Befehle an einem Diagnoseport zu empfangen und zu verarbeiten. Aber es könnte wirklich alles sein. Die Hauptidee ist, dass es etwas über einen langen Zeitraum beobachtet ; Es führt keine Abfolge von Aufgaben aus .
Allgemeine Java-Weisheit sagt: Niemals instanziieren Thread
, ExecutorService
stattdessen eine verwenden. (Siehe z. B. diese Antwort. ) Aber was ist der Vorteil? Die Verwendung eines Thread- Pools als Mittel zum Erstellen eines einzelnen Threads mit langer Laufzeit erscheint sinnlos. Wie wäre es besser, als wenn ich das schreiben würde?
class Foobar {
public Foobar() {
this.threadFactory = Executors.defaultThreadFactory();
...
}
public Foobar(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
...
}
public void start() {
fooThread = threadFactory.newThread(new Runnable() { ... });
fooThread.setDaemon(true);
fooThread.start();
}
...
}
Hinweis: Diese Frage scheint meiner ähnlich zu sein, aber die Antworten sagen nur, wie ein Thread-Pool verwendet wird, nicht warum .
quelle
Antworten:
Ich denke, dass "Nie" ein zu starkes Wort ist. Es ist eher die zweite Regel der Optimierung: "Noch nicht".
Meiner Meinung nach besteht der Hauptgrund für die Verwendung eines Executor-Dienstes darin, die Anzahl der ausgeführten Threads zu verwalten. Wenn Sie beliebigen Klassen erlauben, ihre eigenen Threads zu erstellen, finden Sie möglicherweise schnell 1.000 CPU-gebundene (oder ständig kontextumschaltende) Threads. Ein Executor-Service löst dieses Problem, indem er Einschränkungen für die Thread-Erstellung bereitstellt.
Ein zweiter Grund ist, dass das richtige Starten eines Threads einige Überlegungen erfordert:
System.exit()
, um Ihr Programm herunterzufahren.Das heißt, es gibt sicherlich Fälle, in denen es angebracht ist, Threads hochzufahren, anstatt sich auf einen Thread-Pool zu verlassen.
"Extern generiert" ist kontextabhängig. Der klassische Fall ist der Thread am Ende einer Nachrichtenwarteschlange oder eines Sockets, der diese Warteschlange abfragen und eine Aktion ausführen muss (was das Versenden einer Aufgabe an einen Pool beinhalten kann).
Es könnte sich jedoch auch auf Ereignisse beziehen, die außerhalb eines bestimmten Moduls generiert wurden: Ich halte es beispielsweise für durchaus vernünftig, dass Log4J
AsyncAppender
einen eigenen Thread hochfährt, anstatt zu erwarten, dass die Anwendung einen Pool bereitstellt.quelle