Asynchrone, nicht blockierende, ereignisgesteuerte Programmierung scheint der letzte Schrei zu sein. Ich habe ein grundlegendes konzeptionelles Verständnis dessen, was dies alles bedeutet. Ich bin mir jedoch nicht sicher, wann und wo mein Code davon profitieren kann, asynchron zu sein, oder wie ich blockierende E / A-Vorgänge nicht blockieren kann. Ich bin mir sicher, dass ich dazu einfach eine Bibliothek verwenden kann, aber ich interessiere mich mehr für tiefgreifendere Konzepte und die verschiedenen Möglichkeiten, sie selbst zu implementieren.
Gibt es umfassende / definitive Bücher oder andere Ressourcen zu diesem Thema (wie GoF für Design Patterns oder K & R für C, tldp für Dinge wie bash)?
(Hinweis: Ich bin nicht sicher, ob dies tatsächlich eine Frage ist, die mit meiner Frage zum Erlernen der ereignisgesteuerten Programmierung identisch ist. )
Antworten:
Asynchrone Programmierung ist viel mehr eine Philosophie als nur ein weiterer Programmiertrick. Während Ihre letzte Frage hauptsächlich Antworten zu Programmieraspekten enthielt und meine Antwort ein Einzelgänger war, weil er größtenteils theoretisch war, versuche ich, Ihnen eine neue Perspektive zu bieten, die auf der gleichen Linie aufbaut, aber eher Erklärungen als bloße Referenzen.
Hier geht es um einige Grundlagen zum Warum und Wie der asynchronen Programmierung.
Nehmen wir an, Sie gehen in eine Bäckerei (und gehen davon aus, dass der Kuchen nach der Bestellung zubereitet wird) - Sie haben zwei Möglichkeiten: Entweder Sie warten, bis der Kuchen fertig ist, oder Sie geben die Bestellung auf und kehren nach Hause zurück und holen ab später, wenn es fertig ist. Das erste (Warten) ist eine synchrone Methode und später eine asynchrone Methode . Es erübrigt sich zu erwähnen, dass dieses Beispiel eine gute Referenz bietet, warum Sie asynchrone Methoden über synchrone Methoden verwenden sollten.
Ereignisbasierte Programmierung ist nur eine der Möglichkeiten, mit denen asynchrone Systeme erstellt werden können. Sie ist nicht nur ein nützliches Entwurfsmuster, sondern vielmehr ein Architekturmuster. Ich führe Fälle auf, in denen diese Theorie praktisch nützlich ist, in der Hoffnung, dass sie Klarheit bringt
Eines der ersten Beispiele für asynchrone Systeme ist Unix System IO. Wir wissen zwar
read()
,write()
undselect()
Aufrufe blockieren sogar den Programmfluss, aber innerhalb des Betriebssystems sind sie asynchron, dh der Kernel weiß im Allgemeinen, dass das Blockiergerät (auch bekannt als Festplatte) einige Zeit braucht, um den Puffer zu füllen, bis eine solche Zeit CPU frei ist von diesem jeweiligen Thread und damit ist der Thread als (nicht bereit) geparkt. Siehe 1. Moris Bach "Das Design des Unix-Betriebssystems"Ein weiteres häufigstes Beispiel ist die Mehrheit der UI-Frameworks. Hier werden alle Benutzer-Klicks zunächst über einen Controller abgesetzt, der wiederum die jeweilige Anwendung zurückruft . Wichtig ist, dass solche Rückrufe nicht warten, sonst friert das System ein. Der Rückruf vom UI-Controller an die Back-Ends erfolgt normalerweise asynchron, wenn eine umfangreiche Verarbeitung erforderlich ist.
Ein weiteres gutes Beispiel für asynchrone Programmierung (als reines Entwurfsmuster) ist Active Object. Ein aktives Objekt hat einen eigenen privaten Thread, sodass viele Anforderungen in einer Warteschlange gehalten und einzeln ausgeführt werden können. Lesen Sie dieses Dokument: Aktives Objekt . Dieses Muster wird häufig von Enterprise-Software bis hin zu mobilen Frameworks verwendet. Die gängigen Plattformen Java / EJB und .NET ermöglichen den asynchronen Methodenaufruf von Local oder Remote, wodurch normale Objekte im Wesentlichen zu aktiven Objekten werden können. Aktive Objekte waren bereits in Symbian vorhanden: Aktive Objekte in Symbian OS von Aapo Haapanen (siehe auch: Aktive Objekte in Symbian ). Dies ist nun auch in vorhandenAndroid ).
Abgesehen von Active Object hat derselbe Autor, Douglas C. Schmidt , eine Reihe anderer Arbeiten produziert, die andere Parallelen zu Active Object und auch die asynchronen Muster darstellen. Sehen Sie sich diese Muster für die Ereignisbehandlung an, und Sie finden ein vollständiges Konto in seinem Buch Musterorientierte Softwarearchitektur: Muster für gleichzeitige und vernetzte Objekte - V2
Wenn ein bestimmtes Objekt die API zurückgeben muss, während es im Hintergrund arbeitet, um die Arbeit tatsächlich auszuführen, besteht die übliche Methode darin, ein Multithread-System zu verwenden, um dies zu erreichen. Thread-Systeme gibt es überall von C (posix), C ++ ( boost ) bis Java, C # und so weiter. Active Object ist im Wesentlichen nur eine Abstraktion, die dies verbergen kann. Erfahren Sie, warum Implementierungen von aktiven Objekten nackten Threads vorzuziehen sind. Noch eine gute Lektüre .
Dieses Konzept geht jedoch über Threads oder Objekte in einer Anwendung hinaus und wird asynchron. Eine der besten Einsatzmöglichkeiten besteht in verteilten Systemen, in denen zwei Anwendungen nicht unbedingt aufeinander warten müssen, bis sie koordiniert sind. Gut alt (oder nicht so gut, wie man es auch sieht) RPC war synchron. [Natürlich gibt es auch andere asynchrone RPCs ]. Aber die modernen Alternativen wie Message Oriented Middleware sind aus guten Gründen wirklich asynchron.
Das letzte, aber vielleicht interessanteste, ist die Agentenprogrammierung, die vom asynchronen Kommunikationsmodell profitieren kann .
Während asynchrone Programmierung sexy aussieht , erzeugt sie ihre eigene Komplexität, einschließlich:
... und so weiter.
Es sollte immer nur aus echten Gründen verwendet werden.
Wann sollte man das asynchrone Modell verwenden? Wann sollten Sie einen Hintergrund-Thread einfügen und es dem Aufrufer ermöglichen, asynchron zu arbeiten? Hier einige gute Daumenregeln, wenn sie zutreffen (aber nicht vollständig sind)
Wenn das System eine ernsthafte Ressourcenkonversation durchführen möchte: Beispielsweise möchten Sie eine absolut feste Anzahl von Threads beibehalten. Das asynchrone Muster zwingt das System, die Warteschlange zu implementieren.
Wenn der Anrufer "andere nützliche Dinge tun muss", ist das in der Tat echt. So oft macht der andere Thread, auch wenn er entsperrt wurde, nichts Sinnvolles und fragt nach Ergebnissen. Dies kann in der Tat mehr CPU verbrauchen als das Basis-Synchronmodell.
Wenn Sie in verteilten Systemen ein höheres Maß an Zuverlässigkeit benötigen. (siehe Message Oriented Middleware ).
quelle