2016-12-30 5 views
19

Fehler beim Aufruf von shutdown() an einem Thread-Executor führen zu einer nie beendenden Anwendung. Best practice die ExecutorService herunterzufahren, ist dies:Warum implementiert die ExecutorService-Schnittstelle AutoCloseable nicht?

ExecutorService service = null; 
try { 
    service = Executors.newSingleThreadExecutor(); 
    // Add tasks to thread executor 
    … 
} finally { 
    if(service != null) service.shutdown(); 
} 

Da Java die Try-with-Ressourcen Konzept kennt, wäre es nicht schön, wenn wir dies tun könnte?

try (service = Executors.newSingleThreadExecutor()) 
{ 
    // Add tasks to thread executor 
    … 
} 
+0

Nette Frage obwohl ... das dachte mir nie auf ;-) – GhostCat

+0

Related: http://stackoverflow.com/questions/13883293/turning-an-executorservice-to-daemon-in-java –

+0

Es gibt Tonnen von "findigen" nicht-'Verschlüsseln' APIs im JDK –

Antwort

17

Das ExecutorService hat tatsächlich zwei Abschaltung bezogenen Methoden; basierend auf der einfachen Tatsache, dass beide Möglichkeiten zum Herunterfahren eines Dienstes sinnvoll sind.

Also: wie würden Sie dann automatisch einen Dienst schließen? In einer konsistenten Weise, die für alle funktioniert ?!

Also die vernünftige Erklärung in meinen Augen: Sie können einen ExecutorService nicht zu einem AutoClosable machen, da dieser Dienst keine einzige "close" -ähnliche Operation hat; aber zwei!

Und wenn Sie denken, dass Sie einen solchen automatischen Schließungsservice gut gebrauchen könnten, wäre es eine Sache von 5 Minuten, Ihre eigene Implementierung mit "Delegation" zu schreiben! Oder wahrscheinlich 10 Minuten, weil Sie eine Version erstellen würden, die shutdown() als close-Operation aufruft; und eine, die stattdessen shutdownNow() tut.

+0

Ich denke, wir brauchen hier keine Implementierungsaspekte zu diskutieren. Ich bin immer empfindlich in Bezug auf die Verwendung von Flags (boolesch wie Schalter) für solche Dinge. Aber lass uns nicht hingehen ... denn ich denke, das wäre am Ende eine ziemlich fruchtlose Diskussion. – GhostCat

+0

Sie haben wahrscheinlich Recht;) Was ich wirklich sagen wollte, ist, dass es vollständig möglich ist, die Funktionalität von 'ExecutorService' in eine Klasse zu verpacken, die' AutoCloseable' unterstützt. – ParkerHalo

+0

Zusätzliches Argument, ExecutorService AutoClosable in JDK nicht zu machen - das ist ein Service, kein Rückgriff ... Genau der gleiche Grund für ExceturService nicht zu erweitern. –

-1

Bei Try-with-resources handelt es sich um das automatische Schließen von Lesern/Streams, wobei ExecutorService Aufgaben mit einem Thread-Pool ausführt.

Also ich bin nicht wirklich sicher, ob es eine Parallele zwischen den beiden gibt, dass wir daran denken können, Try-with-resources auch auf ExecutorServices anzuwenden.

AKTUALISIERT
Zitiert Java Language Specification:

Ein Try-mit-Ressourcen-Anweisung mit Variablen parametriert (bekannt als Ressourcen), die vor der Ausführung des try-Block initialisiert und automatisch geschlossen, in der umgekehrten Reihenfolge, aus der sie initialisiert wurden, nach Ausführung des try-Blocks. catch-Klauseln und eine finally-Klausel sind oft unnötig, wenn Ressourcen automatisch geschlossen werden.

Die Spezifikation nennt die Variablen "Ressourcen". So bin ich nicht sicher, ob ExecutorService kann als Ressource bezeichnet werden und so glaube nicht, ExecutorService als Parallele zur Leser/Bäche/Statement/ResultSet/Verbindung usw.

9

Dies ist eine mittelmäßige Abhilfe

ExecutorService service = Executors.newSingleThreadExecutor(); 
try (Closeable close = service::shutdown) { 

} 

Natürlich dürfen Sie niemals zwischen die Anweisung und die try Anweisung etwas setzen, noch die service lokale Variable nach der try Anweisung verwenden.

Angesichts der Vorbehalte, verwenden Sie einfach finally statt.

0

Ich sehe nicht, wo AutoCloseable für einen Executor nützlich ist. try-with-resources ist für Dinge gedacht, die im Rahmen einer Methode initialisiert, verwendet und freigegeben werden können. Dies funktioniert hervorragend für Dateien, Netzwerkverbindungen, JDBC-Ressourcen usw., wo sie schnell geöffnet, benutzt und aufgeräumt werden. Aber ein Executor, insbesondere ein Threadpool, ist etwas, das Sie für eine lange Zeit, wahrscheinlich über die Lebensdauer der Anwendung, verfügbar haben wollen, und wird in Dinge wie Singleton-Dienste eingefügt, die eine Methode haben, die das DI-Framework kennt Rufen Sie beim Herunterfahren der Anwendung auf, um den Executor zu bereinigen. Dieses Verwendungsmuster funktioniert ohne Try-with-Resources.

Ein großer Motivator hinter try-with-resources ist auch sicherzustellen, dass Ausnahmen nicht maskiert werden. Das ist bei den Executoren keine so große Überlegung, das Exception-Throwing wird in den Tasks stattfinden, die an den Executor übergeben werden. Exception-Masking ist kein Problem.

Verwandte Themen