2014-05-01 12 views
9

ich vor kurzem über Quasar lesen, die „leichten“/Go-like „Benutzermodus“ Threads auf die JVM bietet (es hat auch eine Erlang inspiriert Schauspieler System wie Akka aber das ist nicht die Hauptfrage)Leichte Fäden in Akka

zum Beispiel:

package jmodern; 

import co.paralleluniverse.fibers.Fiber; 
import co.paralleluniverse.strands.Strand; 
import co.paralleluniverse.strands.channels.Channel; 
import co.paralleluniverse.strands.channels.Channels; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     final Channel<Integer> ch = Channels.newChannel(0); 

     new Fiber<Void>(() -> { 
      for (int i = 0; i < 10; i++) { 
       Strand.sleep(100); 
       ch.send(i); 
      } 
      ch.close(); 
     }).start(); 

     new Fiber<Void>(() -> { 
      Integer x; 
      while((x = ch.receive()) != null) 
       System.out.println("--> " + x); 
     }).start().join(); // join waits for this fiber to finish 
    } 
} 

Soweit ich den Code zu verstehen ist oben nicht laichen alle JVM/Kernel-Threads, wird alles getan, was in Benutzermodus Threads (oder so behaupten sie), die billiger sein soll (nur wie Go-Routinen, wenn ich richtig verstanden habe)

Meine Frage ist das - soweit ich das verstehe, in Akka basiert alles noch auf JVM Threads, die meistens auf native OS Kernel-Threads (z. Pthreads in POSIX-Systemen), z.B. Soweit ich weiß, gibt es keine Benutzermodus-Threads/gehe wie Co-Routinen/Lightweight-Threads in Akka, habe ich das richtig verstanden?

Wenn ja, dann wissen Sie, ob es eine Design-Wahl ist? Oder gibt es in Akka in Zukunft einen Plan für Leichtgewichte?

Mein Verständnis ist, dass, wenn Sie eine Million Actors haben, aber die meisten von ihnen blockieren, dann Akka mit viel weniger physikalischen Threads umgehen kann, aber wenn die meisten von ihnen nicht blockiert sind und Sie noch etwas Reaktionsfähigkeit vom System benötigen Service Millionen von kleinen Anfragen für das Streaming einiger Daten), dann kann ich die Vorteile einer Benutzermodus Threading-Implementierung sehen, die viel mehr "Threads" am Leben mit geringeren Kosten der Schaffung von Switching und Beendigung (natürlich der einzige Vorteil ist die Reaktionsfähigkeit für viele Kunden gleichmäßig zu teilen, aber Reaktionsfähigkeit ist immer noch wichtig)

Ist mein Verständnis mehr oder weniger korrekt? Bitte korrigieren Sie mich, falls ich falsch liege.

* Ich könnte Benutzer-Modus-Threads mit Go/Co-Routinen und Lightweight-Threads völlig verwirren, die obige Frage beruht auf meinem schlechten Verständnis, dass sie alle einer der gleichen sind.

+1

Das ist, was ich aus meiner Erfahrung mit Python erinnere. Und es ist keine direkte Antwort, aber es könnte nützlich sein. Sowohl Benutzer/Lightweight-Threads als auch tatsächliche Systemthreads haben ihre Verwendung. Es läuft darauf hinaus, beide bieten Nebenläufigkeit, aber nur Systemthreads bieten Parallelität. Wenn Sie also schwere Berechnungen durchführen, werden Sie durch die Verwendung von Benutzer-Threads keinen Boost bekommen, aber Sie werden von System-Threads profitieren. In einer anderen Situation, in der Sie nur einen CPU-Kern haben und einen Server benötigen, ist die Verwendung von Benutzer-Threads die einzige Lösung. – Andrey

+0

Ja, das verstehe ich auch, z. Benutzer-Threads sind nur gut zum Bereitstellen einer "guten Nutzung" der CPU, z. Das Umschalten zwischen 2 Benutzer-Threads, die manchmal IO blockieren, ist billiger als die Verwendung von Full-blast-Threads. Sie nicht Parallelität, aber Sie tun eine bessere Auslastung der CPU, wenn ich das richtig verstanden –

+0

einen Blick auf meine Antwort haben Sie, kann es hilfreich sein: http://stackoverflow.com/questions/29680718/relinquish-the-thread -cpu-bis-async-call-complete-in-akka-and-java/29748613 # 29748613 – circlespainter

Antwort

8

Akka ist eine sehr flexible Bibliothek und ermöglicht es Ihnen, Schauspieler planen mit (im Wesentlichen läuft es durch eine Kette von Eigenschaften zu, dass nach unten) einem einfachen Merkmale ExecutionContext, die, wie Sie, Runnable s führen akzeptiert sehen und irgendwie Sie. Soweit ich sehen kann, ist es wahrscheinlich möglich, eine Bindung an etwas wie Quasar zu schreiben und es als "Backend" für Akka-Akteure zu verwenden.

Allerdings bieten Quasar und ähnliche Bibliotheken wahrscheinlich spezielle Dienstprogramme für die Kommunikation zwischen Fasern. Ich weiß auch nicht, wie sie mit blockierenden Aufgaben wie I/O umgehen würden, wahrscheinlich hätten sie auch einen Mechanismus dafür. Ich bin mir nicht sicher, ob Akka wegen grüner Fäden korrekt über grüne Fäden laufen kann. Quasar scheint auch auf Bytecode-Instrumentierung angewiesen zu sein, und dies ist eine ziemlich fortgeschrittene Technik, die viele Auswirkungen haben kann, die verhindern, dass Akka unterstützt wird.

Allerdings sollten Sie sich bei der Verwendung von Akka-Schauspielern nicht wirklich um das geringe Gewicht von Fäden sorgen. Tatsächlich ist Akka perfekt in der Lage, Millionen von Akteuren auf dem Einzelsystem zu erschaffen (siehe here), und all diese Schauspieler werden gut funktionieren.

Dies wird durch geschickte Planung über spezielle Arten von Thread-Pools, wie z. B. Fork-Join-Thread-Pool, erreicht. Dies bedeutet, dass, wenn die Akteure bei einer lang andauernden Berechnung nicht blockiert werden, sie eine Anzahl von Threads übertreffen können, die wesentlich geringer ist als die Anzahl dieser Akteure. Sie können beispielsweise einen Thread-Pool erstellen, der höchstens 8 Threads verwendet (einen für jeden Kern eines 8-Core-Prozessors), und alle Actor-Aktivitäten werden für diese Threads geplant.

Akka Flexibilität ermöglicht es Ihnen, genau Dispatcher zu konfigurieren für bestimmte Akteure zu verwenden, wenn es gebraucht wird. Sie können dedizierte Dispatcher für Akteure erstellen, die in lang andauernden Aufgaben wie dem Datenbankzugriff verbleiben. Weitere Informationen finden Sie unter here.

Also, kurz gesagt, nein, Sie brauchen keine Userland-Threads für Akteure, weil Akteure nicht eins zu eins auf native Threads abbilden (es sei denn, Sie forcieren sie, das ist aber das sollte um jeden Preis vermieden werden).

+0

Weniger Threads - weniger Kontextwechsel bei gleicher Latenz. Also, kurz, ja, Sie könnten in Erwägung ziehen, Userland-Threads zu verwenden, wenn Sie können. –

+0

"Dies wird durch geschicktes Planen über spezielle Arten von Thread-Pools erreicht" <- Wo würde ich mehr Informationen darüber bekommen, wie dies tatsächlich geschieht (in der einfachsten Form)? – Franz

+0

@Franz Ich bin über die einfachste Form nicht sicher, aber Sie können in der akka beim Lesen [etwa Disponenten] (http://doc.akka.io/docs/akka/2.4/scala/dispatchers.html) starten docs und fahren Sie dann direkt mit der Dokumentation für den [fork-join-Thread-Pool] fort (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html). Sie können auch über Fork-Join Thread-Pools googlen, finden Sie viele Tutorials und Erklärungen. –

2

Akka Akteure sind im Wesentlichen asynchronen und das ist, warum Sie eine Menge von ihnen haben können, während Quasar Schauspieler (ja, Quasar einen Schauspieler Implementierung zu bietet), das auf Erlang ganz in der Nähe ist, sind Synchron oder Sperr aber sie verwenden Fasern anstatt Java (dh zur Zeit OS) Threads, so können Sie immer noch viele von ihnen mit der gleichen Leistung wie Async aber einen Programmierstil genauso einfach wie bei der Verwendung von regulären Threads und Blockieren von Anrufen haben.

I/O wird durch Integrationen gehandhabt: Quasar includes a framework to convert both async and sync APIs into fiber-blocking und Comsat enthalten viele solcher Integrationen bereits (eines mit Java NIO ist direkt in Quasar enthalten).

My reply to another question enthält weitere Informationen.