{"id":4100,"date":"2018-03-04T20:14:56","date_gmt":"2018-03-04T18:14:56","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=4100"},"modified":"2018-03-04T20:14:56","modified_gmt":"2018-03-04T18:14:56","slug":"completionservice-und-executorcompletionservice","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2018\/03\/completionservice-und-executorcompletionservice\/","title":{"rendered":"CompletionService und ExecutorCompletionService"},"content":{"rendered":"<p>Die invokeAll(\u2026)-Methoden aus dem ExecutorService sind praktisch, wenn es darum geht, mehrere Aufgaben nebenl\u00e4ufig abzusenden, und sp\u00e4ter die Ergebnisse einzusammeln. Allerdings ist die R\u00fcckgabe vom Typ List&lt;Future&lt;T&gt;&gt; und wir werden nicht informiert, wenn ein Ergebnis vorliegt. Wir k\u00f6nnen zwar die Liste immer wieder ablaufen und jedes Future-Objekte mit isDone() fragen ob es fertig ist, aber das ist keine ideale L\u00f6sung.<\/p>\n<p>Mit java.util.concurrent.CompletionService\u00a0gibt es eine weitere Java-Schnittstelle \u2013 die keinen Basistyp erweitert \u2013 mit der wir ein Callable oder Runnable arbeiteten lassen k\u00f6nnen und sp\u00e4ter nacheinander die Ergebnisse einsammeln k\u00f6nnen, die fertig sind. Die Java-Bibliothek bringt mit ExecutorCompletionService\u00a0eine Implementierung der Schnittstelle mit, die intern die fertigen Ergebnisse in einer Queue sammelt, und wir k\u00f6nnen die Queue abfragen. Schauen wir uns das in einem Beispiel an.<\/p>\n<pre>ExecutorService executor = Executors.newCachedThreadPool();\r\n\r\n<strong>CompletionService&lt;Integer&gt; completionService =<\/strong>\r\n\r\n<strong>\u00a0 new ExecutorCompletionService&lt;&gt;( executor )<\/strong>;\r\n\r\nList.of( 4, 3, 2, 1 ).forEach( duration -&gt; <strong>completionService.submit<\/strong>( () -&gt; {\r\n\r\n\u00a0 TimeUnit.SECONDS.sleep( duration );\r\n\r\n\u00a0 return duration;\r\n\r\n} ) );\r\n\r\n\r\n\r\nfor ( int i = 0; i &lt; 4; i++ ) {\r\n\r\n\u00a0 try {\r\n\r\n\u00a0\u00a0\u00a0 System.out.println( <strong>completionService.take()<\/strong>.get() );\r\n\r\n\u00a0 }\r\n\r\n\u00a0 catch ( InterruptedException | ExecutionException e ) {\r\n\r\n\u00a0\u00a0\u00a0 e.printStackTrace();\r\n\r\n\u00a0 }\r\n\r\n}\r\n\r\nexecutor.shutdown();<\/pre>\n<p>Der Typ ExecutorCompletionService erwartet im Konstruktor einen Executor, der den Code ausf\u00fchren soll; wir setzen einen Thread-Pool ein. CompletionService hat zwei submit(\u2026)-Methoden:<\/p>\n<ul>\n<li>Future&lt;V&gt; submit\u200b(Runnable task, V result)<\/li>\n<li>Future&lt;V&gt; submit\u200b(Callable&lt;V&gt; task)<\/li>\n<\/ul>\n<p>Abgesendet werden vier Callable-Exemplare, die 4, 3, 2, 1 Sekunden warten und ihre Wartezeit am Ende zur\u00fcckgeben. Nat\u00fcrlich wird als erstes das Callable mit der R\u00fcckgabe 1 fertig, dann 2, usw.<\/p>\n<p>F\u00fcr die R\u00fcckgaben interessiert sich unser Programm nicht, denn es nutzt die take()-Methode. Insgesamt hat CompletionService drei Entnahme-Methoden:<\/p>\n<ul>\n<li>Future&lt;V&gt; take()<br \/>\nLiefert das Ergebnis von der ersten abgeschlossenen Aufgabe und entfernt es von der internen Queue. Liegt kein Ergebnis an, wartet die Methode.<\/li>\n<li>Future&lt;V&gt; poll()<br \/>\nLiefert das Ergebnis von der ersten abgeschlossenen Aufgabe und entfernt es von der internen Queue. Liegt kein Ergebnis ist, wartet poll() nicht, sondern liefert null.<\/li>\n<li>Future&lt;V&gt; poll\u200b(long timeout, TimeUnit unit)<br \/>\nWartet wir take() auf ein Ergebnis, doch kommt es nach dem Ablauf von timeout nicht, liefert die Methode wie poll() als R\u00fcckgabe null.<\/li>\n<\/ul>\n<p>Was der Schnittstelle fehlt ist eine Methode, die die verblendende Anzahl liefert. Wir m\u00fcssen in unserem Code daher einen Z\u00e4hler als extra Variable einf\u00fchren.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die invokeAll(\u2026)-Methoden aus dem ExecutorService sind praktisch, wenn es darum geht, mehrere Aufgaben nebenl\u00e4ufig abzusenden, und sp\u00e4ter die Ergebnisse einzusammeln. Allerdings ist die R\u00fcckgabe vom Typ List&lt;Future&lt;T&gt;&gt; und wir werden nicht informiert, wenn ein Ergebnis vorliegt. Wir k\u00f6nnen zwar die Liste immer wieder ablaufen und jedes Future-Objekte mit isDone() fragen ob es fertig ist, aber [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11],"tags":[],"class_list":["post-4100","post","type-post","status-publish","format-standard","hentry","category-insel"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4100","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=4100"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4100\/revisions"}],"predecessor-version":[{"id":4101,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/4100\/revisions\/4101"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=4100"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=4100"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=4100"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}