Ich werde zusammenfassen, was ich nicht verstehe. Es tut mir leid, es zu posten, obwohl ich nicht sicher bin. Bitte sag mir wer weiß.
Parallelverarbeitung in Java = Multithread-Programmierung.
Thread ist eine Klasse, die Threads verarbeitet. Starten Sie den Thread mit start. Da run in start ausgeführt wird, erben Sie Thread und überschreiben Sie run.
Runnable ist eine Schnittstelle der Klasse, die der Einstiegspunkt ist. Übergeben Sie es an Thread und lassen Sie es mit start laufen. Da es sich um eine Schnittstelle handelt, implementieren und implementieren Sie run.
Nur die Thread-Klasse kann einen neuen Thread starten. Das Verhalten wird ausgeführt. Ob Thread geerbt oder Runnable implementiert werden soll, hängt davon ab, ob das Muster der Vorlagenmethode oder das Strategiemuster ausgewählt werden soll. In der Regel wird das Strategiemuster unter dem Gesichtspunkt der Klassenabhängigkeit übernommen.
Ich bin mir nicht sicher, ob Thread die Runnable-Schnittstelle implementiert. Da es run implementiert, scheint es nicht falsch zu sein, aber es ist verwirrend. Vergessen Sie für den normalen Gebrauch die Implementierung von Runnable. Ich weiß nicht, wo es nützlich sein wird. Es scheint eine Debatte darüber zu geben, wenn Java 1.0 veröffentlicht wird, was bedeutet, dass es schwer zu verstehen ist.
Referenz Kishida no Hatena Thread und Runnable
Seiichi Yoshidas Homepage Java-Threads und Speicherlecks
Das Executor-Framework wurde in Java 1.5 eingeführt, um die Aufgabe der Steuerung von Thread zu übernehmen, da es nach seiner Verwendung nicht mehr verwendet werden kann und selbst wenn es in großen Mengen generiert wird, Druck auf die Ressourcen ausübt. Durch die Kontrolle können sich Programmierer auf das Aufgabendesign konzentrieren. "Steuern von Threads" bedeutet, dass Threads gemäß dem Worker-Thread-Muster zusammengefasst werden, damit sie effizient arbeiten können.
Executor implementiert das Befehlsmuster, sodass der Thread die Aufgabe ausführen kann, ohne sich dessen bewusst zu sein.
Die Executor Service-Oberfläche erweitert Executor um Terminierungs- und Nachverfolgungsfunktionen. Aufgaben können durch Herunterfahren deaktiviert werden, und Aufgaben können anhand des Rückgabewerts Future of Submit verfolgt werden.
Die Future-Klasse ist eine Implementierung des Future-Musters. Wenn Sie Future per Submit erhalten möchten, übergeben Sie Callable als Aufgabe. Callable wird ähnlich wie Runnable verwendet. Der einzige Unterschied besteht darin, ob Sie das Ergebnis mit Senden erhalten oder nicht. Callable erbt nicht von Runnable. Senden kann auch ein Runnable empfangen, aber das Ergebnis scheint sich zu ändern (ich bin nicht sicher, wie es sich ändern wird, Futuer ist null?). Wenn Sie einreichen, können Sie Callable verwenden. Der Unterschied zwischen Callable und Runnable ist verwirrend. Ich wünschte, ich könnte Future mit Runnable zurückgeben. RunnableFuture Interface, das sowohl Runnable als auch Future ist, verstehe ich nicht.
Executor und ExecutorService werden normalerweise nicht von Ihnen selbst implementiert. Holen Sie sich Executors als Fabrik. Da es einen Scheduled Executor Service usw. gibt, habe ich [API] überprüft (https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/Executors.html). Executors hat auch einen Runnable to Callable-Konverter, daher denke ich, dass Callable ein Runnable ist.
Dies ist auch ein Gefühl, mit dem Musternamen zu sprechen. Es ist also schmerzhaft, wenn Sie das Entwurfsmuster nicht kennen.
Referenz Editor für nicht funktionierende Programmierer Java Executor ist praktisch
Ein Framework, das maximale Geschwindigkeit anstrebt, indem das Executor-Framework für Arbeiten optimiert wird, die rekursiv in kleine Einheiten unterteilt werden können. Der WorkStealing-Algorithmus wird verwendet, um den Prozess zu beschleunigen. Eingeführt in Java 1.7.
Work Stealing ist ein Algorithmus, der Arbeit stiehlt. Fork-Aufgaben fein und setzen Sie sie in die Warteschlange. Wenn der Worker-Thread die Aufgaben aus der Warteschlange empfängt, stehlen Sie die Aufgaben in anderen Warteschlangen, wenn alle Aufgaben in der Warteschlange abgeschlossen sind.
ForkJoinPool, die Kernfunktion des ForkJoin-Frameworks, ist eine Implementierungsklasse von ExecutorService, und ForkJoinTask ist eine Implementierungsklasse von Future. ForkJoinPool implementiert den WorkStealing-Algorithmus.
ForkJoinTask ist eine abstrakte Klasse, erbt jedoch nicht direkt. Wenn es kein Ergebnis zurückgibt, erbt es RecursiveAction, und wenn es ein Ergebnis zurückgibt, erbt es RecursiveTask und implementiert eine Taskklasse. ForkJoinPool ruft compute von execute oder submit auf, also implementieren Sie den Prozess in compute. Das Ergebnis ist Zukunft.
Wie wir schon oft gesehen haben, müssen Sie bei der Multithread-Programmierung häufig zwischen der Rückgabe und der Nichtrückgabe von Ergebnissen wählen. Ich war mir nicht sicher, was der Unterschied war. Ist es schneller, es nicht zurückzugeben?
ParallelStream Parallelverarbeitungsfunktion der Stream-API, die ein funktionales Paradigma enthält. Eingeführt in Java 1.8.
Dies ist sehr einfach, da Sie einen Stream aus einem Satz wie Collection generieren und eine parallele Verarbeitung mit einer parallelen Aufnahme realisieren können. Dies ist einfach, da es möglich ist, die funktionale Verarbeitung ohne Nebenwirkungen präzise zu beschreiben, indem sie über eine funktionale Schnittstelle implementiert wird.
Die Verarbeitung mit Nebenwirkungen (ändert den Status) bei der Parallelverarbeitung ist tabu. Beachten Sie jedoch, dass Java auch über eine Funktionsoberfläche verfügt, die Nebenwirkungen hat.
Wenn jedoch eine Feinabstimmung erforderlich ist, ist es besser, das Executor-Framework zu verwenden. In einigen Fällen ist seriell schneller, und nur weil es einfach ist, heißt das nicht, dass Sie alles parallel machen können. Ich bin mir nicht sicher, wie ich es richtig verwenden soll, weil es schwierig ist, eine Linie zu ziehen.
Referenz Legend of Java Concurrency/Parallelism -Yuichi Sakuraba
Recommended Posts