2 Stimmen

Java-Thread hält bei I/O-Operation nicht an

Ich hatte den Eindruck, dass in Java ein Thread eine Pause macht und anderen Threads die Möglichkeit gibt, während blockierender E/A-Operationen (wie Socket.read() oder DataGramsocket.receive()) etwas zu tun. Aus irgendeinem Grund führt in meiner Multi-Thread-Netzwerkanwendung ein Aufruf von receive() dazu, dass alle anderen Threads verhungern (der Thread, der receive() aufgerufen hat, wird zum Big Boss und gibt niemals die Kontrolle ab, wodurch er für immer blockiert! )

Warum sollte das geschehen? Ich hatte früher genau dieselbe Anwendung, aber statt UDP war sie TCP-basiert. Socket.read() hat den Thread immer angehalten und anderen erlaubt, ein wenig zu arbeiten, wenn er zu lange blockiert war.

-- zusätzliche Informationen -- Die TCP-Version meines benutzerdefinierten Threads war dieser Code: http://www.dwgold.com/code/proxy/proxyThread.java.txt

Mein neuer Code (UDP-Version) ist im Wesentlichen derselbe, wurde aber ein wenig modifiziert, um UDP-Methoden und -Stil zu verwenden. Ich habe dann zwei dieser Threads erstellt und beide mit Start aufgerufen. Der erste Thread blockiert immer und lässt den anderen in der UDP-Version nie arbeiten.

1voto

delfuego Punkte 13864

Es scheint, dass Sie einen InputStream verwenden, und nach die JDK-Dokumente für InputStream.read() wird das Lesen genau so blockiert, wie Sie es beschrieben haben - bis die Daten empfangen werden, ein Ende der Datei erreicht wird oder eine Ausnahme ausgelöst wird.

Für mich stellt sich also die Frage: Warum lässt die TCP-Version Ihres Codes zu, dass der Block unterbrochen wird? Das scheint keinen Sinn zu ergeben. Vielleicht unterteilt Ihr TCP-Code die Lesevorgänge in einzelne, ausreichend kurze Abschnitte, so dass der Thread die Möglichkeit hat, zwischen den einzelnen Aufrufen von read() zu springen?

Bei näherer Betrachtung sehe ich, dass der Unterschied darin besteht, dass die TCP-Version Ihres Codes Daten über den InputStream empfängt, der von Socket bereitgestellt wird, während die UDP-Version Ihres Codes Daten direkt von der eigenen receive()-Methode von DatagramSocket empfängt. Ich gehe also davon aus, dass es sich hierbei um einen grundlegenden Unterschied zwischen den beiden angebotenen Funktionen handelt (InputStream.read und DatagramSocket.receive). Haben Sie darüber nachgedacht, die Methode DatagramPacket.setSoTimeout eine Zeitüberschreitung für den Empfangsblock des Sockets zu setzen und dann die SocketTimeoutException abzufangen, wenn sie durch den Aufruf von receive() ausgelöst wird, der eine Zeitüberschreitung verursacht? Sie sollten in der Lage sein, dies zu implementieren, um zu erreichen, was Sie wollen.

UPDATE : Wenn man noch weiter schaut, scheint es, dass die Methode DatagramSocket.receive ist synchronisiert . Der Weg, das Verhalten zu erklären, das Sie sehen, ist, dass Sie zwei Threads starten, die versuchen, die gleiche DatagramSocket-Instanz zu verwenden - wenn zwei Threads versuchen, receive() auf der gleichen DatagramSocket-Instanz auszuführen, wird einer die Instanz blockieren, bis sie fertig ist, und der andere wird blockiert werden. ein Beitrag in den Sun-Foren, der dies beschreibt auch). Könnte dies das sein, was passiert - Sie verwenden den gleichen DatagramSocket für beide Threads wieder?

0voto

Arnaud Punkte 390

Das kann daran liegen, dass die Java-Threads Threads der Benutzerebene sind (im Gegensatz zu Threads der Kernel-Ebene). Ein Thread der Kernel-Ebene kann mehrere Threads der Benutzerebene enthalten. Wenn jedoch ein Thread der Benutzerebene auf io wartet, hat der Kernel keine Möglichkeit, nur diesen Thread der Benutzerebene in eine Warteschlange zu stellen, er kann nur den gesamten Kernel-Thread in die Warteschlange stellen (Threads der Benutzerebene werden auf der Benutzerebene geplant, nicht auf der Kernel-Ebene). Infolgedessen kann/wird ein einzelner Thread der Benutzerebene, der auf io wartet, alle anderen Threads der Benutzerebene (von diesem Kernel-Thread) blockieren.

-1voto

jarnbjo Punkte 33136

Es gibt wirklich keine Erklärung für das von Ihnen beschriebene Verhalten, dass ein Lesezugriff auf einen InputStream von einem Socket dazu führen sollte, dass "alle anderen Threads" pausieren. Starten Sie zufällig mehrere Threads, die alle vom selben Socket lesen und meinen Sie eigentlich, dass alle diese die Fäden hängen? In diesem Fall würde ich erwarten, dass die vom Socket gelesenen Daten willkürlich auf die Threads verteilt werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X