


Dieser Artikel stellt hauptsächlich das relevante Wissen über die Wiederverwendung von Java IO vor. Er ist sehr gut und hat Referenzwert.
Für die gleichzeitige Verarbeitung des Servers Was wir brauchen, ist: Jede Millisekunde kann der Server die innerhalb dieser Millisekunde empfangenen Nachrichten auf Hunderten verschiedener TCP-Verbindungen umgehend verarbeiten. Gleichzeitig können Hunderttausende Nachrichten auf dem Server vorhanden sein, die in der letzten Sekunde nicht empfangen wurden Einige Sekunden lang ist eine relativ inaktive Verbindung zum Senden und Empfangen von Nachrichten erforderlich. Die gleichzeitige Verarbeitung mehrerer Verbindungen, bei denen Ereignisse auftreten, wird als Parallelität bezeichnet. Die gleichzeitige Verarbeitung von Zehntausenden oder Hunderttausenden Verbindungen ist eine hohe Parallelität. Das Ziel der gleichzeitigen Programmierung des Servers besteht darin, eine unendliche Anzahl gleichzeitiger Verbindungen zu verarbeiten und gleichzeitig eine effiziente Nutzung von Ressourcen wie der CPU aufrechtzuerhalten, bis die physischen Ressourcen zum ersten Mal erschöpft sind.
Es gibt viele Implementierungen von Modellen für die gleichzeitige Programmierung, die einfachste ist mit „Threads“ gebündelt und ein Thread verwaltet den gesamten Lebenszyklus einer Verbindung. Vorteile: Dieses Modell ist einfach genug, es kann komplexe Geschäftsszenarien implementieren und gleichzeitig kann die Anzahl der Threads viel größer sein als die Anzahl der CPUs. Die Anzahl der Threads kann jedoch nicht unendlich erhöht werden. Da der Zeitpunkt der Ausführung eines Threads durch den Planungsalgorithmus des Betriebssystemkerns bestimmt wird, berücksichtigt der Planungsalgorithmus nicht, dass ein bestimmter Thread möglicherweise nur eine Verbindung bedient. Er übernimmt ein einheitliches Gameplay: Führen Sie ihn aus, wenn die Zeitscheibe abgelaufen ist Dieser Thread Nach der Ausführung müssen Sie weiter schlafen. Dieses Hin- und Herwechseln zwischen Aufwachen und Ruhen von Threads ist günstig, wenn die Häufigkeit gering ist. Wenn jedoch die Gesamtzahl der Threads im Betriebssystem groß ist, ist es teuer (verstärkt), da sich dieser technische Planungsverlust auf die Threads auswirkt Der Zeitpunkt, zu dem der Geschäftscode ausgeführt wird. Beispielsweise ist die Ausführungseffizienz der meisten Threads mit inaktiven Verbindungen zu diesem Zeitpunkt zu niedrig. Sie wachen auf und konkurrieren um CPU-Ressourcen bedeutet, dass die Anzahl der privaten Unternehmensthreads, die aktive Verbindungen verarbeiten, verringert wird und die Möglichkeit, die CPU zu erhalten, verringert wird. Die CPU ist der Kern der Wettbewerbsfähigkeit, und ihre Ineffizienz wirkt sich auf den gesamten BIP-Durchsatz aus. Unser Ziel ist es, Hunderttausende von Verbindungen gleichzeitig zu verarbeiten. Wenn Tausende von Threads auftreten, kann die Ausführungseffizienz des Systems einer hohen Parallelität nicht mehr gerecht werden.
Für die Programmierung mit hoher Parallelität gibt es derzeit nur ein Modell, das im Wesentlichen die einzig wirksame Methode ist. Die Nachrichtenverarbeitung auf der Verbindung kann in zwei Phasen unterteilt werden: Warten auf die Bereitstellung der Nachricht und Nachrichtenverarbeitung. Bei Verwendung des standardmäßigen blockierenden Sockets (z. B. ein Thread, der oben zum Verarbeiten einer Verbindung gebündelt ist) werden diese beiden Phasen häufig zu einer kombiniert, sodass der Thread, der den Socket-Code betreibt, warten muss, bis die Nachricht bereit ist Dies führt dazu, dass der Thread bei hoher Parallelität häufig in den Ruhezustand wechselt und wieder aufwacht, was sich auf die Effizienz der CPU-Nutzung auswirkt.
Die Programmiermethode mit hoher Parallelität besteht natürlich darin, die beiden Phasen zu trennen. Das heißt, der Codeabschnitt, der darauf wartet, dass die Nachricht bereit ist, wird vom Codeabschnitt getrennt, der die Nachricht verarbeitet. Dies erfordert natürlich auch, dass der Socket nicht blockierend ist. Andernfalls kann das Codesegment, das die Nachricht verarbeitet, leicht dazu führen, dass der Thread in die Ruhezustandswartephase eintritt, wenn die Bedingungen nicht erfüllt sind. Die Frage ist also: Wie erreicht man diese Phase des Wartens, bis die Nachricht fertig ist? Schließlich wartet es noch, was bedeutet, dass der Thread noch schlafen muss! Die Lösung besteht darin, aktiv abzufragen oder einen Thread auf alle Verbindungen warten zu lassen! Dies ist IO-Multiplexing. Beim Multiplexen geht es darum, auf die Bereitstellung von Nachrichten zu warten, aber es können mehrere Verbindungen gleichzeitig verarbeitet werden! Es kann auch „warten“, sodass der Thread möglicherweise auch in den Ruhezustand versetzt wird. Dies spielt jedoch keine Rolle, da es eins-zu-viele ist und alle Verbindungen überwachen kann. Wenn unser Thread zur Ausführung aktiviert wird, müssen auf diese Weise einige Verbindungen vorhanden sein, die für die Ausführung durch unseren Code bereitstehen, was effizient ist! Es gibt nicht so viele Threads, die um die Verarbeitung der Phase „Warten auf die Fertigstellung der Nachricht“ konkurrieren, und die ganze Welt ist endlich klar!
Unter Linux wurden sie hauptsächlich ausgewählt und abgefragt. Ihre Verwendungsmethoden scheinen sehr unterschiedlich zu sein das gleiche.
Auch die Effizienz ist unterschiedlich, weshalb epoll select komplett ersetzt hat.
Lassen Sie uns kurz darüber sprechen, warum Epoll Select ersetzt.
Wie bereits erwähnt, besteht die Kernlösung für hohe Parallelität darin, dass ein Thread das „Warten auf die Bereitstellung von Nachrichten“ für alle Verbindungen verwaltet. In diesem Punkt sind Epoll und Select unumstritten. Aber wählen Sie eine Sache falsch aus. Wie wir im Eröffnungskapitel von gesagt haben, gibt es möglicherweise nur Hunderte von aktiven Verbindungen pro Millisekunde, während die restlichen Hunderttausende von Verbindungen vorhanden sind ist während dieser Millisekunde inaktiv. Die Methode zur Verwendung von „select“ lautet wie folgt:
Zurückgegebene aktive Verbindungen ==select (alle zu überwachenden Verbindungen)
Wann wird die select-Methode aufgerufen? Sie sollten dies aufrufen, wenn Sie herausfinden möchten, welche aktiven Verbindungen Pakete empfangen haben. Daher wird der Aufruf von select häufig aufgerufen, wenn die Parallelität hoch ist. Auf diese Weise muss geprüft werden, ob diese häufig genannte Methode effizient ist, da ihr geringfügiger Effizienzverlust durch das Wort „häufig“ verstärkt wird. Gibt es einen Effizienzverlust? Offensichtlich müssen Hunderttausende Verbindungen überwacht werden und es werden nur Hunderte aktive Verbindungen zurückgegeben, was an sich ineffizient ist. Nach der Erweiterung werden Sie feststellen, dass select nicht in der Lage ist, Zehntausende gleichzeitiger Verbindungen zu verarbeiten.
Schauen Sie sich einige Bilder an. Wenn die Anzahl gleichzeitiger Verbindungen weniger als 1.000 beträgt, ist die Anzahl ausgewählter Ausführungen nicht häufig und es scheint keinen großen Unterschied zu Epoll zu geben:
Sobald jedoch die Anzahl der Parallelitäten zunimmt, werden die Mängel von Select durch die „häufige Ausführung“ unendlich vergrößert. Je mehr Parallelität vorhanden ist, desto offensichtlicher ist:
Lassen Sie uns darüber sprechen, wie Epoll das Problem löst. Es verwendet geschickt drei Methoden, um das zu erreichen, was die Auswahlmethode bewirkt:
Neuer Epoll-Deskriptor==epoll_create()
epoll_ctrl(Epoll-Deskriptor, hinzufügen oder Löschen alle zu überwachenden Verbindungen)
Die zurückgegebene aktive Verbindung==epoll_wait (epoll-Deskriptor)
Der Hauptvorteil dieser Vorgehensweise besteht darin, zwischen häufigen Aufrufen und selten aufgerufenen Vorgängen zu unterscheiden. Beispielsweise wird epoll_ctrl seltener aufgerufen, während epoll_wait sehr häufig aufgerufen wird. Zu diesem Zeitpunkt hat epoll_wait fast keine Eingabeparameter, was viel effizienter ist als select. Darüber hinaus erhöht es die Anzahl der Eingabeparameter nicht, wenn gleichzeitige Verbindungen zunehmen, was zu einer Verringerung der Kernel-Ausführungseffizienz führt.
Wie wird Epoll implementiert? Tatsächlich ist es sehr einfach, aus diesen drei Methoden zu ersehen, dass es intelligenter ist als „select“, da es nicht erforderlich ist, jedes Mal alle zu überwachenden Verbindungen zu übergeben, wenn epoll_wait häufig aufruft, „welche Verbindungen sich bereits in der Nachrichtenvorbereitung befinden“. Bühne". von. Dies bedeutet, dass im Kernelmodus eine Datenstruktur verwaltet wird, um alle zu überwachenden Verbindungen zu speichern. Diese Datenstruktur ist ein rot-schwarzer Baum, und das Hinzufügen und Reduzieren seiner Knoten wird über epoll_ctrl abgeschlossen. Es ist ganz einfach:
Der rot-schwarze Baum unten links im Bild besteht aus allen zu überwachenden Verbindungen. Die verknüpfte Liste oben links zeigt alle derzeit aktiven Verbindungen. Wenn epoll_wait ausgeführt wird, überprüft es daher nur die verknüpfte Liste oben links und gibt die Verbindung in der verknüpften Liste oben links an den Benutzer zurück. Kann die Ausführungseffizienz von epoll_wait auf diese Weise niedrig sein?
Schließlich werfen wir einen Blick auf die beiden von Epoll bereitgestellten Spielmethoden ET und LT, nämlich den übersetzten Edge-Trigger und den horizontalen Trigger. Tatsächlich sind diese beiden chinesischen Namen einigermaßen passend. Diese beiden Verwendungsmethoden zielen immer noch auf Effizienzprobleme ab, dienen jedoch lediglich dazu, die von epoll_wait zurückgegebene Verbindung genauer zu machen.
Zum Beispiel müssen wir überwachen, ob der Schreibpuffer einer Verbindung frei ist. Wenn er „beschreibbar“ ist, können wir den Antwortaufruf write aus dem Benutzermodus an den Client senden. Wenn die Verbindung jedoch beschreibbar ist, befindet sich unser „Antwort“-Inhalt möglicherweise noch auf der Festplatte. Was ist, wenn der Lesevorgang auf der Festplatte zu diesem Zeitpunkt noch nicht abgeschlossen ist? Der Thread darf nicht blockiert sein, damit die Antwort nicht gesendet wird. Beim nächsten epoll_wait wird die Verbindung jedoch möglicherweise an Sie zurückgegeben, und Sie müssen prüfen, ob Sie sie verarbeiten möchten. Möglicherweise verfügt unser Programm über ein weiteres Modul, das speziell Festplatten-E/A verarbeitet und eine Antwort sendet, wenn die Festplatten-E/A abgeschlossen ist. Erfüllt epoll_wait also jedes Mal, wenn diese „beschreibbare“ Verbindung zurückgegeben wird, die nicht sofort verarbeitet werden kann, die Erwartungen des Benutzers?
So entstanden die ET- und LT-Modi. LT bedeutet, dass jede Verbindung, die den erwarteten Status erfüllt, in epoll_wait zurückgegeben werden muss, damit alle gleich behandelt werden und sich auf einer horizontalen Linie befindet. Dies ist bei ET nicht der Fall, das präzisere Rückverbindungen bevorzugt. Wenn im obigen Beispiel die Verbindung zum ersten Mal beschreibbar wird und das Programm keine Daten in die Verbindung schreibt, gibt epoll_wait die Verbindung beim nächsten Mal nicht zurück. ET wird als Edge-Trigger bezeichnet, was bedeutet, dass epoll_wait nur dann ausgelöst wird, wenn die Verbindung von einem Zustand in einen anderen wechselt. Es ist ersichtlich, dass die Programmierung von ET viel komplizierter ist. Zumindest muss die Anwendung darauf achten, dass die von epoll_wait zurückgegebene Verbindung nicht angezeigt wird: Wenn sie beschreibbar ist, werden die Daten nicht geschrieben, sondern sie erwartet die nächste „beschreibbare“ Verbindung. Wenn es lesbar ist, werden die Daten nicht gelesen, aber beim nächsten Mal wird erwartet, dass sie „lesbar“ sind.
Natürlich wird es in allgemeinen Anwendungsszenarien keinen großen Leistungsunterschied geben. Der mögliche Vorteil von ET besteht darin, dass die Anzahl der Aufrufe von epoll_wait reduziert wird und in einigen Szenarien die Verbindung nicht aktiviert wird ist nicht notwendig (Dieses Aufwachen bezieht sich auf die Rückkehr von epoll_wait). Aber wenn es wie das oben erwähnte Beispiel ist, liegt es manchmal nicht nur an einem Netzwerkproblem, sondern hängt mit dem Anwendungsszenario zusammen. Natürlich sind die meisten Open-Source--Frameworks auf Basis von ET geschrieben. Was das Framework betrifft, verfolgt es rein technische Probleme und strebt natürlich nach Perfektion
Das obige ist der detaillierte Inhalt vonDetaillierte grafische und textliche Erläuterung der IO-Wiederverwendung in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于结构化数据处理开源库SPL的相关问题,下面就一起来看一下java下理想的结构化数据处理类库,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于PriorityQueue优先级队列的相关知识,Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于java锁的相关问题,包括了独占锁、悲观锁、乐观锁、共享锁等等内容,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于多线程的相关问题,包括了线程安装、线程加锁与线程不安全的原因、线程安全的标准类等等内容,希望对大家有帮助。

本篇文章给大家带来了关于Java的相关知识,其中主要介绍了关于关键字中this和super的相关问题,以及他们的一些区别,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于枚举的相关问题,包括了枚举的基本操作、集合类对枚举的支持等等内容,下面一起来看一下,希望对大家有帮助。

封装是一种信息隐藏技术,是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法;封装可以被认为是一个保护屏障,防止指定类的代码和数据被外部类定义的代码随机访问。封装可以通过关键字private,protected和public实现。

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于设计模式的相关问题,主要将装饰器模式的相关内容,指在不改变现有对象结构的情况下,动态地给该对象增加一些职责的模式,希望对大家有帮助。


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

EditPlus chinesische Crack-Version
Geringe Größe, Syntaxhervorhebung, unterstützt keine Code-Eingabeaufforderungsfunktion

MantisBT
Mantis ist ein einfach zu implementierendes webbasiertes Tool zur Fehlerverfolgung, das die Fehlerverfolgung von Produkten unterstützen soll. Es erfordert PHP, MySQL und einen Webserver. Schauen Sie sich unsere Demo- und Hosting-Services an.

Sicherer Prüfungsbrowser
Safe Exam Browser ist eine sichere Browserumgebung für die sichere Teilnahme an Online-Prüfungen. Diese Software verwandelt jeden Computer in einen sicheren Arbeitsplatz. Es kontrolliert den Zugriff auf alle Dienstprogramme und verhindert, dass Schüler nicht autorisierte Ressourcen nutzen.

Dreamweaver CS6
Visuelle Webentwicklungstools

PHPStorm Mac-Version
Das neueste (2018.2.1) professionelle, integrierte PHP-Entwicklungstool
