Freunde, die Java -Parallelitätspakete verwendet haben, sind möglicherweise mit der Zukunft vertraut (Schnittstelle). Die Zukunft wird in einigen Domänensprachen (wie Alice ML) sogar direkt auf der Syntaxebene unterstützt.
Hier nehmen wir java.util.concurrent.future als Beispiel, um kurz über die spezifische Arbeitsmethode der Zukunft zu sprechen. Das zukünftige Objekt selbst kann als explizite Referenz angesehen werden, ein Hinweis auf die Ergebnisse der asynchronen Verarbeitung. Aufgrund seiner asynchronen Natur ist das Objekt, das es zu Beginn der Erstellung möglicherweise nicht gibt (z. B. ist es noch in Betrieb, Netzwerkübertragung oder Warten). Zu diesem Zeitpunkt kann der Programmfluss, der die Zukunft erhält, nicht eilig, das von Zukunft verwiesene Objekt zu verwenden, und kann alles andere tun, was Sie wollen. zwei Situationen sein:
Ich hoffe, dieses Objekt verfügbar zu sehen und einige verwandte Follow-up-Prozesse zu vervollständigen. Wenn es wirklich nicht verfügbar ist, können Sie auch andere Zweigprozesse eingeben.
"Ohne dich verliert mein Leben seine Bedeutung, und selbst wenn das Meer weg ist, werde ich auf Sie warten." -Zeit)
Für den ersteren Fall können Sie feststellen, ob das referenzierte Objekt bereit ist, um zukünftige () zu rufen.
Get (langfristig, Timeunit Unit) wartet darauf, dass das Objekt durch synchrones Blockieren fertig ist. Ob die tatsächliche Laufzeit sofort blockiert oder zurückgegeben wird, hängt von der Anrufzeit von Get () und der Reihenfolge des Objekts fertig.
Einfach ausgedrückt, der zukünftige Modus kann den datengesteuerten Parallelitätsanforderungen in kontinuierlichen Prozessen erfüllen und nicht nur Leistungsverbesserungen bei der gleichzeitigen Ausführung, sondern auch die Einfachheit und Eleganz kontinuierlicher Prozesse erhalten.
Vergleich mit anderen gleichzeitigen Entwurfsmustern
Zusätzlich zur Zukunft umfassen andere gemeinsame Entwurfsmuster von Parallelität "Callback-gesteuert (in Multi-Threaded-Umgebung)", "Nachricht/Ereignis (im Schauspielermodell)" usw. ".
Callback ist der häufigste asynchrone Parallelitätsmodus, der eine hohe Unmittelbarkeit und ein einfaches Schnittstellendesign aufweist. Aber im Vergleich zu Zukunft sind seine Nachteile sehr offensichtlich. Erstens werden Rückrufe in Multithread -Umgebungen im Modul -Thread ausgeführt, der den Rückruf auslöst, was bedeutet, dass bei der Schreiben von Rückrufmethoden der Thread -Ausschluss in Betracht gezogen werden muss. Führen Sie Rückrufe für Benutzeranwendungen aus, die ebenfalls relativ unsicher sind, da Sie nicht feststellen können, wie lange es dauern wird oder welche Ausnahmen sie auftreten werden, was die Unmittelbarkeit und Zuverlässigkeit dieses Moduls indirekt beeinflussen kann. Sequenz. Daher ist die Rückrufschnittstelle für Szenarien geeignet, in denen nur einfache Aufgaben in einem Rückruf ausgeführt werden müssen und nicht mit anderen Prozessen kombiniert werden müssen.
Die Nachteile der oben genannten Rückrufmodi sind genau die Stärken der Zukunft. Da die Verwendung von Zukunft auf natürliche Weise asynchrone Datentreiber in sequentielle Prozesse einbezieht, müssen Sie überhaupt keine Thread-Probleme in Betracht ziehen. unten "faul zukünftig" erwähnt werden. Andererseits müssen Module, die zukünftige Schnittstellen anbieten, keine Sorgen über Zuverlässigkeitsprobleme wie Rückrufschnittstellen und deren potenzielle Unmittelbarkeit auf dieses Modul machen.
Ein weiteres häufiges gleichzeitiges Entwurfsmuster ist "Message (Ereignis) gesteuert", das im Allgemeinen im Akteurmodell verwendet wird: Der Serviceantragsteller sendet eine Nachricht an den Dienstanbieter und führt dann weiterhin nachfolgende Aufgaben aus, die sich nicht auf die Serviceverarbeitungsergebnisse beruhen und hängt davon ab, wenn Sie sich darauf verlassen müssen. Obwohl diese staatlich maschinenbasierte gleichzeitige Steuerung besser für Kontinuitätsfolgeprozesse als für Rückrufe geeignet ist, müssen Entwickler den kontinuierlichen Prozess in mehreren staatspezifischen Subprozessen entsprechend dem Ruf des asynchronen Dienstes in mehrere staatspezifische Subprozesse einschneiden, was die Komplexität der Entwicklung künstlich erhöht. Die Verwendung des zukünftigen Modus kann dieses Problem vermeiden und müssen keine kontinuierlichen Prozesse für asynchrone Anrufe brechen. Eine Sache sollte jedoch beachtet werden: Die Future.get () -Methode kann die Thread -Ausführung blockieren, sodass sie normalerweise nicht direkt in das herkömmliche Akteurmodell eingebaut werden kann. (Das Coroutine-basierte Akteurmodell kann diesen Konflikt besser lösen)
Die Flexibilität von Future spiegelt sich auch in seiner freien Wahl zwischen Synchronisation und asynchronen Entscheidungen wider. die Bedürfnisse des Prozesses. Sie können beispielsweise entscheiden, ob Sie diese Lücke verwenden möchten, um andere Aufgaben zu erledigen, basierend darauf, ob die Daten bereit sind, was für die Implementierung des Mechanismus "Asynchronous Zweigvorhersage" sehr bequem ist.
Die Ableitung der Zukunft
Zusätzlich zu den oben genannten grundlegenden Formen hat Future auch reichhaltige Ableitungen. Hier sind einige gemeinsame.
Faule Zukunft
Im Gegensatz zu allgemeinen Futures beginnt die faule Zukunft nicht aktiv mit der Vorbereitung des referenzierten Objekts zu Beginn der Schöpfung, wartet jedoch, bis das Objekt vor Beginn der entsprechenden Arbeit angefordert wird. Daher ist die faule Zukunft selbst nicht dazu gedacht, Parallelität zu erreichen, sondern nimmt das Speichern unnötiger Rechenressourcen als Ausgangspunkt ein, und seine Auswirkung ähnelt Lambda/Verschluss. Zum Beispiel müssen Sie beim Entwerfen bestimmter APIs möglicherweise eine Reihe von Informationen zurückgeben, und die Berechnung einiger von ihnen kann erhebliche Ressourcen konsumieren. Der Anrufer ist jedoch möglicherweise nicht über all diese Informationen besorgt. Daher kann die Bereitstellung von Objekten, die mehr Ressourcen in Form fauler Zukunft benötigen, Ressourcen sparen, wenn der Anrufer keine spezifischen Informationen verwenden muss.
Darüber hinaus kann die faule Zukunft auch verwendet werden, um unnötige gegenseitige Ausschlüsse zu vermeiden, die durch vorzeitige Erfassung oder Ressourcensperrung verursacht werden.
Versprechen
Versprechen kann als spezielle Filiale der Zukunft angesehen werden. Versprechen werden jedoch verwendet, um Szenarien ausdrücklich darzustellen, in denen asynchrone Prozesse nicht direkt vom Service Caller ausgelöst werden. Zum Beispiel wird die Timing -Steuerung der zukünftigen Schnittstelle, der asynchronen Prozess, vom Anrufer nicht ausgelöst, sondern von der Systemuhr. Abonnent, aber vom Abonnenten. Daher hat die Versprechen -Schnittstelle im Vergleich zur Standard -Zukunft im Allgemeinen eine zusätzliche SET () oder Fulfill () -Schinschnittstelle.
Wiederverwendbare Zukunft
Eine regelmäßige Zukunft ist einmalig, was bedeutet, dass das zukünftige Objekt selbst, wenn Sie asynchrone Verarbeitungsergebnisse erzielen, seine Bedeutung verliert. Speziell gestaltete Zukunft kann aber auch wiederverwendet werden, was für Daten, die mehrmals geändert werden können, sehr nützlich ist. Zum Beispiel ermöglicht die von der oben erwähnte Taobao-verteilte Abonnement-Framework bereitgestellte Schnittstelle im zukünftigen Stil die WaitNext () -Methode (äquivalent zu Future.get ()). Letzter Anruf. Der Vorteil dieses Designs besteht darin, dass der Benutzer der Schnittstelle zu jeder geeigneten Zeit auf Änderungen der Abonnementdaten reagieren kann oder einfach über eine unendliche Schleife in einem unabhängigen Thread und gleichzeitig andere Zeitaufgaben oder sogar auf mehrere Aufgaben warten kann gleichzeitig. Vereinfachte Beispiele sind wie folgt:
für (;;) {plan = GetNextScheduledTaskTime (); .}} doScheduledTask ();} Nutzung der Zukunft
Lassen Sie uns zunächst einen Code in Java auflisten.
//: Parallelität/scallledemo.javaimport java.util.concurrent.*; Java.util importieren String CALL () {return "Ergebnis von TaskWithresult" + id; New ArrayList <Future <String >> (); versuchen : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::: ;} catch (InterruptedException e) : Ergebnis von Task withresult 0Result of tasksUtResult 1Result of taskswithresult 2res ult of tasksultUm die Verwendung der Zukunft zu erläutern, wird zunächst die ausführende Objekt -EXEC -Aufrufe von Subschritt () ein zukünftiges Objekt generiert, das den spezifischen Typ des Callable -Rückgabeergebnisses zur Parametrizität verwendet. Sie können die Isdone () -Methode verwenden, um abzufragen, ob die Zukunft abgeschlossen wurde. Wenn die Aufgabe abgeschlossen ist, hat sie ein Ergebnis und Sie können die Get () -Methode aufrufen, um das Ergebnis zu erhalten. Sie können auch Get () ohne Isdone () überprüfen. Sie können die Get () -Funktion mit einem Zeitlimit aufrufen oder isdone () zuerst aufrufen, um festzustellen, ob die Aufgabe erledigt ist, und dann Get () aufrufen.