NIO Selector: Wie man einen neuen Kanal während der Auswahl richtig registriert

8

Ich habe eine Unterklasse Thread mit einer privaten Selector und eine öffentliche register(SelectableChannel channel, ...) -Methode, die es anderen Threads erlaubt, Kanäle für den Selektor zu registrieren.

Wie beantwortet hier blockiert der register() des Kanals während der Auswahl select() / select(long timeout) , also müssen wir es tun wakeup() der Selektor.

Mein Thread wählt unbegrenzt aus (es sei denn, er wird unterbrochen) und erreicht tatsächlich die nächste Auswahl, bevor der register() des Kanals aufgerufen wird. Also dachte ich, ich benutze eine einfache Sperre mit synchronized Blöcken, um sicherzustellen, dass register() zuerst passiert.

Der Code: (irrelevanter Code wurde zur besseren Lesbarkeit entfernt)

%Vor%

Diese einfache Sperre ermöglicht register() , bevor der Thread mit der nächsten Auswahlschleife fortfährt. Soweit ich getestet habe, funktioniert das wie angenommen.

Fragen: Ist das ein "guter" Weg, oder gibt es irgendwelche gravierenden Nachteile? Wäre es besser, eine Liste oder eine Warteschlange zu verwenden (wie hier hier empfohlen), um Kanäle für die Registrierung zu speichern, oder eine komplexere Sperre wie dies stattdessen? Was wären die Vor- / Nachteile davon? Oder gibt es "noch bessere" Wege?

    
riha 10.10.2012, 14:53
quelle

3 Antworten

3

Ich bin wirklich überrascht, dass die Lock-Erfassung mit dem leeren Block zur Kompilierzeit nicht entfernt wird. Ziemlich cool, dass es funktioniert. Ich meine, es funktioniert, es ist präventiv, es ist nicht der schönste Ansatz, aber es funktioniert. Es ist besser als ein Schlaf, da es vorhersehbar ist und da Sie den Weckruf verwenden, wissen Sie, dass der Fortschritt nach Bedarf und nicht nach einem regelmäßigen Update erfolgt, wenn Sie sich ausschließlich auf das Auswahl-Timeout verlassen.

Der Hauptnachteil dieses Ansatzes besteht darin, dass Sie sagen, dass Aufrufe zur Registrierung alles andere übertrumpfen, sogar Serviceanforderungen. Das mag in Ihrem System zutreffen, aber normalerweise ist dies nicht der Fall. Ich würde sagen, dass dies ein mögliches Problem ist. Ein kleineres Problem, das eher vorausschauend ist, ist, dass Sie SelectorThread selbst sperren, was in diesem Fall eine Art größeres Objekt ist. Nicht schlecht, aber nicht großartig, wenn Sie expandieren, muss diese Sperre nur dann dokumentiert und berücksichtigt werden, wenn andere Clients diese Klasse verwenden. Persönlich würde ich mit einem neuen Schloss gehen, um unvorhergesehene zukünftige Gefahren zu vermeiden.

Ich persönlich mag die Warteschlangentechniken. Sie weisen Ihren Threads Rollen zu, wie ein Master und die Mitarbeiter auf diese Weise. Während alle Arten von Kontrolle auf dem Master passieren, wie nach jeder Auswahlprüfung für mehr Registrierungen aus einer Warteschlange, lösche und fasse alle Leseaufgaben ab, handle irgendwelche Änderungen in der gesamten Verbindungseinrichtung (trennt usw.) ... Die "bs" -Zwischenläufigkeit Das Modell scheint dieses Modell recht gut zu akzeptieren und es ist ein hübsches Standardmodell. Ich denke nicht, dass es eine schlechte Sache ist, da es den Code ein bisschen weniger hacky, mehr testbar und einfacher imo zu lesen macht. Es braucht nur ein bisschen mehr Zeit, um zu schreiben.

Ich gebe zwar zu, dass es lange her ist, seit ich das letzte Mal geschrieben habe, es gibt andere Bibliotheken da draußen, die sich um die Warteschlangen kümmern.

Grizzly Nio Framework , während ein wenig alt, das letzte Mal, als ich es verwendet habe, war die Haupt-Runloop nicht schlecht. Es stellt eine Menge der Warteschlangen für Sie bereit.

Apache Mina Ähnlich, da es ein Warteschlangen-Framework bietet.

Aber am Ende kommt es darauf an, woran Sie gerade arbeiten.

  • ist es ein Ein-Mann-Projekt, nur um mit dem Framework herumzuspielen?
  • ist es ein Stück Produktionscode, von dem Sie jahrelang leben wollen?
  • ist es ein Stück Produktionscode, auf dem Sie iterieren?

Sofern Sie nicht planen, dies als Kernstück einer Dienstleistung zu verwenden, die Sie Kunden anbieten, würde ich sagen, dass Ihre Vorgehensweise in Ordnung ist. Es kann nur auf lange Sicht Wartungsprobleme haben.

    
Greg Giacovelli 11.10.2012, 05:12
quelle
4

Behandeln Sie Selector usw. einfach so, dass sie nicht Thread-sicher sind, führen Sie alle ausgewählten Aktionen für denselben Thread durch, wie Darron vorgeschlagen hat.

Das Nebenläufigkeitsmodell des NIO-Selektors ist Bullshit . Ich muss es ausrufen, denn es ist eine riesige Zeitverschwendung für jeden, der es studieren will. Am Ende ist die Schlussfolgerung, vergiss es, es ist nicht für die gleichzeitige Verwendung.

    
irreputable 10.10.2012 16:48
quelle
2

Alles, was Sie brauchen, ist ein wakeup () vor dem register () und in der Select-Schleife ein kurzer Schlaf, bevor Sie fortfahren, wenn 'ready' gleich Null ist, um register () eine Chance zu geben. Keine zusätzliche Synchronisation: es ist schon schlimm genug; mach es nicht schlimmer. Ich bin kein Fan dieser Warteschlangen Dinge zu registrieren, abzubrechen, zu ändern, Interesse ops, etc: sie nur sequentialisieren Dinge, die wirklich parallel gemacht werden können.

    
EJP 11.10.2012 03:11
quelle

Tags und Links