{"id":51,"date":"2023-09-30T14:25:00","date_gmt":"2023-09-30T13:25:00","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=51"},"modified":"2024-01-08T09:15:25","modified_gmt":"2024-01-08T08:15:25","slug":"effiziente-nebenlaeufigkeit-mit-thread-pools-und-executors-in-java","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=51","title":{"rendered":"Effiziente Nebenl\u00e4ufigkeit mit Thread-Pools und Executors in Java"},"content":{"rendered":"\n<p>In der Welt der Softwareentwicklung spielt die effiziente Verarbeitung von Aufgaben eine entscheidende Rolle. Die M\u00f6glichkeit, Aufgaben parallel abzuarbeiten, verbessert die Leistung von Anwendungen erheblich. Java, als eine der f\u00fchrenden Programmiersprachen, bietet Mechanismen zur Nebenl\u00e4ufigkeit, darunter Thread-Pools und Executors, welche gegen\u00fcber den einfachen Threads <a href=\"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=49\" data-type=\"post\" data-id=\"49\">wie in diesem Artikel<\/a> beschrieben oft zu bevorzugen sind. Dieser Artikel hier widmet sich daher nun der Erkl\u00e4rung und Demonstration dieser Konzepte und zeigt, wie sie in Java verwendet werden k\u00f6nnen, um skalierbare und leistungsstarke Anwendungen zu entwickeln.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Grundlagen der Nebenl\u00e4ufigkeit in Java:<\/strong> Bevor wir uns mit Thread-Pools und Executors befassen, ist es wichtig, die Grundlagen der Nebenl\u00e4ufigkeit in Java zu verstehen. Ein Thread repr\u00e4sentiert einen ausf\u00fchrbaren Codepfad innerhalb eines Programms. Die Erstellung und Verwaltung von Threads erm\u00f6glichen es, Aufgaben gleichzeitig auszuf\u00fchren. Allerdings kann eine \u00fcberm\u00e4\u00dfige Anzahl von Threads zu Ressourcenengp\u00e4ssen und ineffizienter Nutzung der Systemressourcen f\u00fchren.<\/li>\n\n\n\n<li><strong>Thread-Pools:<\/strong> Ein Thread-Pool ist eine Sammlung vorab erstellter Threads, die dazu verwendet werden, Aufgaben aus einer Warteschlange auszuf\u00fchren. Die Idee besteht darin, die Anzahl der Threads zu begrenzen und sie wiederzuverwenden, um eine bessere Kontrolle \u00fcber die Nebenl\u00e4ufigkeit zu haben. Java stellt die <code>ExecutorService<\/code>-Schnittstelle bereit, um Thread-Pools zu erstellen und zu verwalten. Beispielcode f\u00fcr die Erstellung eines einfachen Thread-Pools:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">   int poolSize = 5;\n   ExecutorService executor = Executors.newFixedThreadPool(poolSize);<\/code><\/span><\/pre>\n\n\n<p>Hier wird ein Thread-Pool mit einer festen Gr\u00f6\u00dfe von f\u00fcnf Threads erstellt. Die Gr\u00f6\u00dfe des Pools sollte je nach Anforderungen und Systemressourcen sorgf\u00e4ltig gew\u00e4hlt werden.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\">\n<li><strong>Executors in Java:<\/strong> Executors sind eine h\u00f6here Ebene der Abstraktion \u00fcber Thread-Pools und bieten einen vereinfachten Mechanismus zur Ausf\u00fchrung von Aufgaben nebenl\u00e4ufig. Java stellt verschiedene Implementierungen von <code>ExecutorService<\/code> zur Verf\u00fcgung, die den unterschiedlichen Anforderungen gerecht werden.<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>newFixedThreadPool(int nThreads)<\/code>: Erstellt einen Thread-Pool mit fester Gr\u00f6\u00dfe.<\/li>\n\n\n\n<li><code>newCachedThreadPool()<\/code>: Erstellt einen dynamisch wachsenden Thread-Pool.<\/li>\n\n\n\n<li><code>newSingleThreadExecutor()<\/code>: Erstellt einen Thread-Pool mit nur einem Thread. Beispielcode f\u00fcr die Verwendung von Executors:<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">   ExecutorService executor = Executors.newFixedThreadPool(3);\n\n   for (int i = 0; i <span class=\"hljs-tag\">&lt; <span class=\"hljs-attr\">10<\/span>; <span class=\"hljs-attr\">i<\/span>++) {\n       <span class=\"hljs-attr\">Runnable<\/span> <span class=\"hljs-attr\">task<\/span> = <span class=\"hljs-string\">new<\/span> <span class=\"hljs-attr\">MyTask<\/span>(<span class=\"hljs-attr\">i<\/span>);\n       <span class=\"hljs-attr\">executor.execute<\/span>(<span class=\"hljs-attr\">task<\/span>);\n   }\n\n   <span class=\"hljs-attr\">executor.shutdown<\/span>();<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird ein Thread-Pool mit fester Gr\u00f6\u00dfe erstellt, und zehn Aufgaben (repr\u00e4sentiert durch <code>MyTask<\/code>) werden dem Pool zur Ausf\u00fchrung \u00fcbergeben. Nach Abschluss aller Aufgaben wird der Thread-Pool heruntergefahren.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"4\">\n<li><strong>Arbeiten mit Callable und Future:<\/strong> Neben der Ausf\u00fchrung von Runnable-Aufgaben k\u00f6nnen Thread-Pools auch Callable-Aufgaben verarbeiten, die einen Wert zur\u00fcckgeben. Die <code>Callable<\/code>-Schnittstelle wird in Verbindung mit der <code>Future<\/code>-Schnittstelle verwendet, um das Ergebnis einer Aufgabe abzurufen. Beispielcode f\u00fcr die Verwendung von Callable und Future:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">   Callable&lt;Integer&gt; task = () -&gt; {\n       <span class=\"hljs-comment\">\/\/ Aufgabe, die einen Wert zur\u00fcckgibt<\/span>\n       <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-number\">42<\/span>;\n   };\n\n   Future&lt;Integer&gt; futureResult = executor.submit(task);\n\n   <span class=\"hljs-keyword\">try<\/span> {\n       Integer result = futureResult.get(); <span class=\"hljs-comment\">\/\/ Blockiert, bis das Ergebnis verf\u00fcgbar ist<\/span>\n       System.out.println(<span class=\"hljs-string\">\"Ergebnis: \"<\/span> + result);\n   } <span class=\"hljs-keyword\">catch<\/span> (InterruptedException | ExecutionException e) {\n       e.printStackTrace();\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird eine Callable-Aufgabe erstellt, die einen Integer-Wert zur\u00fcckgibt. Das <code>submit<\/code>-Methode gibt ein <code>Future<\/code>-Objekt zur\u00fcck, das verwendet werden kann, um das Ergebnis abzurufen.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"5\">\n<li><strong>Individuelle Benennung von Threads in Thread-Pools:<\/strong> Bei der Verwendung von Thread-Pools ist es oft hilfreich, Threads individuell zu benennen, um ihre Aufgaben besser zu verfolgen und zu verstehen. In Java k\u00f6nnen Sie dies erreichen, indem Sie eine benutzerdefinierte <code>ThreadFactory<\/code> implementieren und dem Thread-Pool bei der Erstellung \u00fcbergeben. Beispielcode f\u00fcr die individuelle Benennung von Threads:<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">   <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">NamedThreadFactory<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">ThreadFactory<\/span> <\/span>{\n       <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> int threadCount = <span class=\"hljs-number\">0<\/span>;\n       <span class=\"hljs-keyword\">private<\/span> String prefix;\n\n       <span class=\"hljs-keyword\">public<\/span> NamedThreadFactory(String prefix) {\n           this.prefix = prefix;\n       }\n\n       @Override\n       <span class=\"hljs-keyword\">public<\/span> Thread newThread(Runnable r) {\n           Thread thread = <span class=\"hljs-keyword\">new<\/span> Thread(r, prefix + <span class=\"hljs-string\">\"-\"<\/span> + threadCount);\n           threadCount++;\n           <span class=\"hljs-keyword\">return<\/span> thread;\n       }\n   }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird eine einfache <code>NamedThreadFactory<\/code> implementiert, die Threads mit einem benutzerdefinierten Pr\u00e4fix und einer fortlaufend erh\u00f6hten Nummer erstellt. Diese Factory kann dann dem Thread-Pool bei der Initialisierung \u00fcbergeben werden.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">   ExecutorService executor = Executors.newFixedThreadPool(<span class=\"hljs-number\">3<\/span>, <span class=\"hljs-keyword\">new<\/span> NamedThreadFactory(<span class=\"hljs-string\">\"MyThread\"<\/span>));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Nun werden die Threads im Pool mit Namen wie &#8222;MyThread-0&#8220;, &#8222;MyThread-1&#8220;, usw. benannt.<\/p>\n\n\n\n<p>Die Nutzung von Thread-Pools und Executors in Java erm\u00f6glicht eine effiziente Verarbeitung von Aufgaben durch die Kontrolle der Nebenl\u00e4ufigkeit. Durch die Verwendung vorab erstellter Threads und h\u00f6herer Abstraktionsebenen wie Executors k\u00f6nnen Entwickler leistungsf\u00e4hige Anwendungen erstellen, die gut skaliert und ressourceneffizient sind. Die individuelle Benennung von Threads bietet eine zus\u00e4tzliche Ebene der Transparenz und Verst\u00e4ndlichkeit in komplexen Anwendungen, indem sie erm\u00f6glicht, die Aufgaben einzelnen Threads zuzuordnen. Es ist jedoch wichtig, sich der Herausforderungen der Nebenl\u00e4ufigkeit bewusst zu sein, insbesondere in Bezug auf die Thread-Sicherheit, um unerw\u00fcnschte Ergebnisse zu vermeiden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In der Welt der Softwareentwicklung spielt die effiziente Verarbeitung von Aufgaben eine entscheidende Rolle. Die M\u00f6glichkeit, Aufgaben parallel abzuarbeiten, verbessert die Leistung von Anwendungen erheblich. Java, als eine der f\u00fchrenden Programmiersprachen, bietet Mechanismen zur Nebenl\u00e4ufigkeit, darunter Thread-Pools und Executors, welche gegen\u00fcber den einfachen Threads wie in diesem Artikel beschrieben oft zu bevorzugen sind. Dieser Artikel [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-51","post","type-post","status-publish","format-standard","hentry","category-plain_java"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/51","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=51"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/51\/revisions"}],"predecessor-version":[{"id":52,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/51\/revisions\/52"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=51"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=51"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=51"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}