1. Grundkonzepte
IO ist der Prozess des Kopierens von Daten nach Hauptspeicher und externen Geräten (Festplatten, Terminals, Netzwerke usw.). IO ist die zugrunde liegende funktionale Implementierung des Betriebssystems, das durch E/A -Anweisungen abgeschlossen wird.
Alle Sprachlaufzeitsysteme bieten hochrangige Tools für die Durchführung von E/A. (Cs printfscanf, javas objektorientierte Kapselung)
2. Überprüfung von Java Standard IO
Die Java Standard IO-Klassenbibliothek ist eine Abstraktion von IO-Objektorientierungen. Basierend auf der zugrunde liegenden Implementierung lokaler Methoden müssen wir nicht auf die zugrunde liegende Implementierung achten. InputStream/OutputStream: Übertragen Sie jeweils ein Byte. Leser/Schriftsteller: jeweils ein Charakter.
3.NIO EINLEITUNG
NIO ist die Abkürzung von Javanewio, einer neuen API in JDK1.4. Die Eigenschaften, die die Sonne offiziell behauptet, sind wie folgt:
Bietet (Puffer-) Cache -Unterstützung für alle primitiven Typen.
Charakter -Set -Codierungs- und Dekodierungslösungen.
Kanal: Eine neue ursprüngliche I/A -Abstraktion.
Unterstützt die Dateizugriffsschnittstellen für Sperr- und Speicher -zugeordnete Dateien.
Bietet nicht-Bloking, nicht blockierende und hochskalierbare Netzwerk-E/O.
Dieser Artikel wird diese Funktionen erlernen und vorstellen.
4.Buffer & Chanel
Kanal und Puffer sind NIO und die beiden grundlegendsten Datentyp -Abstraktionen.
Puffer:
Es ist ein kontinuierlicher Speicherblock.
Es ist der Transitort zum Lesen oder Schreiben von NIO -Daten.
Kanal:
Die Datenquelle oder das Datenziel von Daten
Eine eindeutige Schnittstelle zur Bereitstellung von Daten für Puffer oder Lesen von Pufferdaten, Pufferobjekte.
Asynchrone E/A -Unterstützung
Beispiel 1: Copyfile.java:
Paket Beispiel; import Java.io.FileInputStream; Import Java.io.FileOutputStream; Import Java.nio.ByTebuffer; Import Java.nio.Channels.Filechannel; öffentliche Klasse Copyfile {public static void main (String [] args) löst Ausnahme aus {String Infile = " "C: //copy.txt"; // Eingabetaste und Ausgabe von Quell- und Zieldateien FileInputStream Fin = New FileInputStream (Infile); FileOutputStream Fout = New FileOutputStream (Outfile); // Eingabe- und Ausgabekanäle Filchannel Fcin = Fin.Getchannel (); FileChannel (); buffer = bytebuffer.alcode (1024); Während (true) {// Methode löschen, setzt der Puffer soweit, dass es Lesedatenpuffer akzeptieren kann. Lesen Sie Daten zu einem anderen Kanalpuffer.flip (); // Schreiben Sie Daten aus dem Ausgangskanal zum Puffer fcout.write (Puffer);}}}Die interne Struktur des Puffers ist wie folgt (die folgende Abbildung wird aus den Informationen kopiert):
Abbildung 2: Puffer interne Struktur
Ein Puffer steuert hauptsächlich den Lese- und Schreibprozess um drei Variablen Position, Grenze und Kapazität. Die Bedeutung dieser drei Variablen ist in der folgenden Tabelle angezeigt:
Parameter | Schreibmodus | Lesemodus |
Position | Die Anzahl der derzeit geschriebenen Einheitsdaten. | Der aktuelle Standort der Einheit Daten gelesen. |
Limit | Es stellt die maximale Anzahl von Daten und Kapazitäten dar, die geschrieben werden können. | Es stellt die maximale Anzahl von Dateneinheiten dar, die gelesen werden können, was mit der Menge der zuvor geschriebenen Einheitsdaten übereinstimmt. |
Kapazität | Pufferkapazität | Pufferkapazität |
Gemeinsame Puffermethoden:
Flip (): Schreibmodus in Lesemodus konvertieren
Rewind (): Position auf 0 zurücksetzen, im Allgemeinen zum wiederholten Lesen verwendet.
Clear (): Löschen Sie den Puffer und bereiten Sie sich darauf vor, erneut geschrieben zu werden (Position wird zu 0, die Grenze wird Kapazität).
compact (): Kopieren Sie ungelesene Daten auf den Kopf des Puffers.
mark (), reset (): Mark kann eine Position markieren, Reset kann auf diese Position zurückgesetzt werden.
Häufige Pufferarten: ByteBuffer, MaptingBuffer, Charbuffer, DoubleBuffer, Floatbuffer, Intbuffer, Longbuffer, Shortbuffer.
Gemeinsame Kanäle: Filechannel, Datagramchannel (UDP), Socketchannel (TCP), ServerSocketchannel (TCP)
Ein einfacher Leistungstest wurde auf dieser Maschine durchgeführt. Mein Laptop führt in Maßen durch. (Siehe den Anhang für den spezifischen Code. Siehe das folgende Beispiel im NIO.Sample.FileCopy -Paket) Laut den Referenzdaten:
Szenario 1: Kopieren Sie eine 370m -Datei
Szenario 2: Drei Threads kopieren gleichzeitig, und jeder Thread kopiert eine 370m -Datei.
Szene | FileInputStream+ FileOutputStream | FileInputStream+ BufferedInputStream+ FileOutputStream | Bytebuffer+ Filechannel | Zugeordneter Bytebuffer +Filechannel |
Szene für eine Zeit (Millisekunden) | 25155 | 17500 | 19000 | 16500 |
Szene 2 Mal (Millisekunden) | 69000 | 67031 | 74031 | 71016 |
5.nio.Charset
Charaktercodierung und Dekodierung: Bytecode selbst sind nur einige Zahlen, die im richtigen Kontext korrekt analysiert werden. Beim Speichern von Daten in ByteBuffer müssen Sie die Codierungsmethode des Zeichensatzes berücksichtigen. Beim Lesen und Anzeigen von ByteBuffer -Daten umfassen Sie den Charaktersatz.
Java.nio.charset bietet eine Reihe von Lösungen für Codierung und Dekodierung.
Wenn Sie unsere häufigste HTTP -Anfrage als Beispiel annehmen, muss die Anfrage bei Anforderung korrekt codiert werden. Die Antwort muss korrekt dekodiert werden, wenn sie erhalten wird.
Der folgende Code sendet eine Anfrage an Baidu und erhält die Ergebnisse für die Anzeige. Das Beispiel zeigt die Verwendung von charSet.
Beispiel 2Baidureader.java
Paket nio.readPage; import Java.nio.Bytebuffer; Import Java.nio.Channels.Socketchannel; Import Java.nio.Charset. private SocketChannel channel;public void readHTMLContent() {try {InetSocketAddress socketAddress = new InetSocketAddress( "www.baidu.com", 80);//step1: Open the connection channel = SocketChannel.open(socketAddress);//step2: Send the request, encode channel.write(charset.encode("GET " + "/ Http/1.1 " +"/r/n/r/n ")); // Schritt 3: Lesen Sie den Daten ByteBuffer Buffer = Bytebuffer.alcode (1024); // Erstellen Sie einen 1024 -byte -Puffer (Kanal. System.out.println (charset.decode (buffer)); // charset.decode -Methode, um Bytes in String -Buffer.Clear (); // Puffer}} catch (ioException e) {System.err.println (E.toString ();} endlich (Kanal! e) {}}}} public static void main (String [] args) {new baidureader (). readhtmlContent ();}}6. Nicht blockierende IO
In Bezug auf nicht blockierende IO werden wir aus den Aspekten des Blockierens, des nicht blockierenden, nicht blockierenden Prinzips und der asynchronen Kern-API verstehen.
Was ist Blockade?
Ein gemeinsamer Netzwerk -IO -Kommunikationsprozess ist wie folgt:
Lassen Sie uns aus diesem Netzwerkkommunikationsprozess verstehen, was Blockierung ist:
Wenn die Verbindung nicht im obigen Vorgang eingetreten ist, muss das Akzeptieren nach dem Laufen nach dem Laufen hängen, und die CPU wird stattdessen andere Threads ausführen.
Wenn die Daten im obigen Prozess nicht fertig sind, blockiert auch die LESER.
Merkmale des Blockierungsnetzwerks IO: Multi-Threading-Mehrfachverbindungen. Jeder Thread hat seinen eigenen Stapelraum und nimmt eine CPU -Zeit in Anspruch. Jeder Thread blockiert, wenn er auf eine externe Bereitschaft trifft. Das Ergebnis der Blockierung ist, dass es zu einer großen Anzahl von Prozesskontextschaltungen führt. Und die meisten Prozesskontextschaltungen können bedeutungslos sein. Nehmen wir beispielsweise an, ein Thread hört auf einen Port zu, und es wird nur wenige Anfragen an einem Tag geben, aber die CPU muss ständig Kontextversuche für den Thread durchführen, und die meisten Schaltanschläge enden in der Blockierung.
Was ist nicht blockiert?
Hier ist eine Metapher:
In einem Bus von A bis B gibt es viele Punkte auf der Straße, die aussteigen können. Der Fahrer weiß nicht, welche Punkte aus dem Bus steigen werden. Wie kann man mit denen umgehen, die besser aus dem Bus steigen müssen?
1. Während des Vorgangs fragt der Fahrer regelmäßig jeden Passagier, ob er am Ziel ankam. Wenn jemand das sagt, hält der Fahrer an und der Passagier steigt aus. (Ähnlich wie die Blockierung)
2. Jeder sagt dem Ticketverkäufer sein Ziel und schläft dann. Der Fahrer interagiert nur mit dem Ticketverkäufer. Wenn er zu einem bestimmten Punkt ankommt, benachrichtigt der Ticketverkäufer den Passagier, aus dem Bus zu steigen. (Ähnlich wie nicht blockierend)
Offensichtlich kann jeder, der ein Ziel erreicht, als Thread angesehen werden, und der Fahrer kann als CPU betrachtet werden. Im Blockierungsstil muss jeder Thread ständig den Kontext befragen und wechseln, um das Ergebnis der Suche nach dem Ziel zu erreichen. Im nicht blockierenden Modus schläft jeder Passagier (Faden) (schläft) und wacht nur auf, wenn die echte externe Umgebung fertig ist. Ein solches Aufwachen wird definitiv nicht blockieren.
Das Prinzip der Nichtblockierung
Schalten Sie den gesamten Vorgang auf kleine Aufgaben und erledigen Sie ihn durch Zusammenarbeit zwischen Aufgaben.
Ein dedizierter Thread behandelt alle IO -Ereignisse und ist für die Verteilung verantwortlich.
Ereignisorientierter Mechanismus: Trigger, wenn ein Ereignis eintrifft, anstatt Ereignisse gleichzeitig zu überwachen.
Thread -Kommunikation: Threads kommunizieren durch Warten, Benachrichtigungen und andere Mittel. Stellen Sie sicher, dass jeder Kontextschalter Sinn macht. Reduzieren Sie unnötige Prozessumschaltung.
Das Folgende ist die Struktur des asynchronen IO:
Reaktor ist die obige metaphorische Rolle des Ticketverkäufers. Der Verarbeitungsfluss jedes Threads besteht wahrscheinlich darin, Daten zu lesen, zu entschlüsseln, die Verarbeitung zu berechnen, zu codieren und Antworten zu senden.
Asynchrone IO -Kern -API
Wähler
Die Kernklasse der asynchronen IO, die Ereignisse auf einem oder mehreren Kanälen erkennen und Ereignisse verteilen kann.
Verwenden Sie einen Select -Thread, um Ereignisse auf mehreren Kanälen anzuhören und die entsprechenden Antworten basierend auf Ereignisentreibern auszulösen. Es ist nicht erforderlich, einen Thread für jeden Kanal zuzuweisen.
SelectionKey
Enthält die Bindung des Kanals, der den Statussinformationen des Ereignisses und der Zeit entspricht.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels über grundlegende Java -Wissensaufsätze. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!