Wann ist Multithreading sinnvoll?

8

Ich denke, ich bekomme die Grundlagen des Multi-Threading mit Java. Wenn ich mich nicht irre, nehmen Sie einen großen Job und finden heraus, wie Sie ihn in mehrere (gleichzeitige) Aufgaben aufteilen. Dann implementieren Sie diese Aufgaben entweder als Runnable s oder Callable s und senden sie alle an eine ExecutorService . (Also zunächst, wenn ich mich so irre, fang bitte an, mich zu korrigieren !!! )

Zweitens muss ich mir vorstellen, dass der Code, den Sie in run() oder call() implementieren, so "parallelisiert" wie möglich sein muss, mit nicht blockierenden Algorithmen usw. Und dass hier der schwierige Teil ist ( Parallelcode schreiben). Richtig? Nicht korrekt?

Aber das wirkliche Problem, das ich immer noch mit Java-Nebenläufigkeit habe (und ich vermute, Nebenläufigkeit im Allgemeinen), und das ist das wahre Thema dieser Frage, ist:

  

Wann ist überhaupt überhaupt ein Multithread möglich?

Ich sah ein Beispiel aus einer anderen Frage zu Stack Overflow, wo das Poster die Erstellung mehrerer Threads zum Lesen und Verarbeiten einer riesigen Textdatei vorschlug (das Buch Moby Dick ) und ein Antworter das Multithreading kommentierte zum Zweck des Lesens von der Platte war eine schreckliche Idee. Ihr Argument dafür war, dass Sie mehrere Threads haben, die den Overhead des Kontextwechsels, on top eines bereits langsamen Prozesses (Festplattenzugriff) einführen.

Das hat mich zum Nachdenken gebracht: Welche Klassen von Problemen eignen sich für Multi-Threading, welche Klassen von Problemen sollten immer serialisiert werden? Vielen Dank im Voraus!

    
IAmYourFaja 29.06.2012, 17:41
quelle

7 Antworten

8

Multi-Threading hat zwei Hauptvorteile, IMO:

  • in der Lage sein, intensive Arbeit über mehrere CPUs / Kerne zu verteilen: Anstatt 3 von 4 CPUs im Leerlauf laufen zu lassen und alles auf einer einzigen CPU auszuführen, teilen Sie das Problem in 4 Teile und lassen jede CPU an ihrem eigenen Teil arbeiten. Dies reduziert die Zeit, die für die Ausführung einer CPU-intensiven Task benötigt wird, und rechtfertigt das Geld, das Sie für Multi-CPU-Hardware ausgegeben haben
  • Reduzieren Sie die Latenz vieler Aufgaben. Angenommen, 4 Benutzer stellen eine Anfrage an einen Webserver, und die Anfragen werden alle von einem einzigen Thread bearbeitet. Angenommen, die erste Anfrage führt zu einer sehr langen Datenbankabfrage. Der Thread befindet sich im Leerlauf und wartet darauf, dass die Abfrage abgeschlossen wird, und die drei anderen Benutzer warten, bis diese Anforderung abgeschlossen ist, um ihre winzige Webseite zu erhalten. Wenn Sie vier Threads haben, sogar mit einer einzelnen CPU, können die zweite, dritte und vierte Anforderung verarbeitet werden, während die lange Datenbankabfrage vom Datenbankserver ausgeführt wird und alle Benutzer zufrieden sind. Daher ist Multithreading besonders wichtig, wenn Sie blockierende E / A-Aufrufe haben, da diejenigen, die E / A-Aufrufe blockieren, die CPU im Leerlauf laufen lassen, anstatt einige andere wartende Tasks auszuführen.

Hinweis: Das Problem beim Lesen von mehreren Threads von derselben Festplatte besteht darin, dass statt der ganzen sequenziellen Datei die Platte gezwungen wird, bei jedem Kontextwechsel zwischen verschiedenen physischen Speicherorten der Festplatte zu wechseln. Da alle Threads darauf warten, dass das Lesen der Festplatte beendet wird (sie sind IO-gebunden), wird das Lesen langsamer, als wenn ein einzelner Thread alles lesen würde. Aber sobald die Daten im Speicher sind, wäre es sinnvoll, die Arbeit zwischen Threads aufzuteilen.

    
JB Nizet 29.06.2012, 17:59
quelle
5
  

Das hat mich zum Nachdenken gebracht: Welche Klassen von Problemen sind angemessen?   Multi-Threading, welche Klassen von Problemen sollten immer serialisiert werden?

Grundsätzlich sollten CPU-intensive Tasks (die viele Daten verarbeiten, wie z. B. In-Memory-Sortierung) parallelisiert werden (wenn möglich) und I / O-gebundene Tasks sollten sequentiell bleiben (wie Disk-I / O). Dies ist ein allgemeiner Hinweis mit einigen Ausnahmen natürlich.

    
Tudor 29.06.2012 17:44
quelle
3
  

Das hat mich zum Nachdenken gebracht: Welche Klassen von Problemen eignen sich für Multi-Threading, welche Klassen von Problemen sollten immer serialisiert werden?

Wenn Sie eine grafische Benutzeroberfläche mit Swing-Komponenten erstellen, dauert es manchmal so lange, bis Sie die Aufgaben, die Sie durch Klicken auf eine Schaltfläche ausführen möchten, so lange sperren, bis Sie die GUI während der Ausführung der Aufgabe sperren / p>

Sie führen die Aufgabe also in einem anderen Thread aus, sodass Sie den GUI-Thread (Swing-Worker-Thread) als Reaktion auf die Swing-Komponenten beibehalten können.

    
Gilbert Le Blanc 29.06.2012 17:48
quelle
3

Multithreading ist wertvoll für:

  • Verteilen Sie die Arbeit auf mehrere CPUs oder mehrere Kerne.
  • Bleiben Sie beim Ausführen einer langen Aufgabe (z. B. Laden einer Datei, Ausführen einer Berechnung) reaktionsfähig.
  • Bleibt reaktionsfähig, während eine Operation ausgeführt wird, die blockieren kann (z. B. Lesen von einem Socket).
Andy Thomas 29.06.2012 17:52
quelle
1

Ich bevorzuge es so ....

  1. Threading ist sehr wichtig bei GUI-basierten Anwendungen.

  2. In Java wird die GUI vom Event Dispatcher Thread behandelt. Es ist immer ratsam, das zu behalten UI-Arbeit am Benutzeroberflächenthread und Nicht-UI-Arbeit am Nicht-UI-Thread. Angenommen, Sie drücken eine Taste und dann geht eine HTTP-Anfrage an einen Webserver, die Verarbeitung findet auf dem Server statt, dann antwortet sie mit dem Ergebnis .. Wenn Sie keinen Nicht-UI-Thread erstellen, um diesen Job zu bearbeiten, dann Ihre GUI wird NICHT REAGIEREN, bis die Antwort des Webservers empfangen wird.

  3. Threads sind auch sehr wichtig in Fällen, in denen mehrere Arbeiten gleichzeitig ausgeführt werden sollen. Das beste Beispiel ist OS . Normalerweise kodiere ich meine Lieblingsmusik und höre gleichzeitig im Internet, usw .... Hier ist Multithreading sehr praktisch, wenn es nur einen Thread gäbe, hätten wir uns nie vorstellen können, was wir können mach heute mit OS.

  4. Mehrere Threads über die CPU hinweg werden für die parallele Verarbeitung einer CPU-intensiven Arbeit verwendet.

  5. Im Fall von Java Servlet wird jede Anforderung, die den Server trifft, von einem separaten Thread behandelt, der vom Container bereitgestellt wird.

Kumar Vivek Mitra 29.06.2012 18:03
quelle
0

Parallelität ist auch in bestimmten Algorithmen sehr nützlich. Zum Beispiel arbeite ich gerade daran, ein Programm zu schreiben, das mithilfe eines genetischen Algorithmus die optimale Lösung für ein kompliziertes Problem berechnet. In einem genetischen Algorithmus haben Sie eine Population von Individuen, die alle eine Fitnessfunktion ausführen müssen. Die Durchführung dieser Fitnesstests wird im Allgemeinen völlig unabhängig voneinander sein, und es wird eine Menge von ihnen durchführen (Sie könnten zum Beispiel Bevölkerungsgrößen von Hunderten haben). Die Parallelisierung kann die Geschwindigkeit eines genetischen Algorithmus dramatisch erhöhen, indem die Zeit verkürzt wird, die für die Ausführung aller Fitnessfunktionen benötigt wird.

Hoffentlich gibt Ihnen das eine Vorstellung davon, worauf Leute sich beziehen, wenn sie von 'CPU-intensiven' Aufgaben sprechen, insbesondere weil nicht alle CPU-intensiven Aufgaben leicht parallel gemacht werden können.

    
MattS 29.06.2012 18:25
quelle
0

99,9% der Threads auf Ihrer Box machen keine CPU-intensive Arbeit. Meine Box hat momentan 1084 Threads und 1% CPU-Auslastung - die 1084 Threads machen überhaupt nichts aus. Sie warten alle, viele auf Signale von anderen Threads, aber vor allem warten viele auf I / O. Der wichtigste und allgegenwärtige Grund für die Verwendung mehrerer Threads in einem präemptiven Multitasking-Betriebssystem besteht darin, die allgemeine I / O-Leistung für eine App zu steigern. Diese Präventivkerne zwingen uns in den Schmerz der Synchronisation, Warteschlangen, Sperren usw. - im Wesentlichen eine andere Designzone, in der eine Anweisung nicht mehr notwendigerweise der anderen folgt. Der Vorteil ist, dass die E / A-Leistung wesentlich besser ist als bei kooperativen Planungssystemen, da alle Threads, die auf einen Treiber für E / A warten, nach der E / A-Vervollständigung sofort bereit gestellt werden können Treiber, der auf einen Hardware-Interrupt reagiert. Async-E / A ändert dies nicht, es verschiebt nur die E / A-Warte auf einen Kernel-Thread-Pool, der Async-Anforderungen auflisten und den Callback-Setup-Benutzer-Thread bereit machen muss, wenn I / O dafür auftritt (während er Benutzercode erzwingt) um zu expliziten State-Maschinen zurückzukehren. Also, welche Klassen von Problemen für Multi-Threading geeignet sind:

1) Überall dort, wo E / A von mehreren Quellen erwartet wird, bei denen die Fertigstellung asynchron erfolgen kann.

2) Wo Threads das App-Design einfacher, schneller und sicherer machen. Wenn 20 "Dinge" gleichzeitig passieren müssen, ist es viel einfacher, apparent "Inline" -Code zu schreiben und es mit 20 Threads auszuführen, als einen State-Machine selbst zu entwickeln, um 20 verschiedene Kontexte zu behandeln. Da sich Threads in einem Prozess Speicher teilen, ist es trivial, riesige Puffer (OK, Pufferreferenzen / Zeiger) in Warteschlangen zu kommunizieren, um z. Kommst Stacks.

3) CPU-intensive Operationen an Multicore-Boxen, insbesondere wo die Datensätze für jeden Thread / Kern für die Cache-Optimierung isoliert werden können.

4) AOB:)

Ohne mehrere Threads und die I / O-Leistung des preemptiven Kernels gäbe es kein BitTorrent, kein Video-Streaming, keine MMP-Spiele, keinen AVI-Player.

Sie könnten jedoch Notepad und MS Word ausführen ...

    
Martin James 30.06.2012 00:32
quelle