# select() ohne NIO - oder wie Worker-Thread sauber beenden?



## thre (29. Aug 2007)

Hi,

ich habe folgendes Problem. Ich habe eine Applikation, in der ein Worker-Thread ein Netzwerkprotokoll Daten bearbeitet. Diesen will ich (z.B. beim Schließen der Applikation) sauber beenden. Hätte ich ein C-Programm, würde ich so vorgehen, dass ich im Thread immer mittels select() und Timeout von z.B. 50ms nachschaue, ob Daten da sind. Wenn das zurückkehrt, würde ich erstmal eine Statusvariable checken, ob ich den Thread beenden soll. Erst dann würde ich auswerten, ob select() nun zurückgegeben hat, ob Daten da sind oder nicht und diese dann entweder bearbeiten oder weiter auf Daten warten.

Dummerweise kann ich mit herkömmlicher I/O in Java den select()-Aufruf nicht simulieren. Zumindest ist mir nichts eingefallen. NIO kann ich nicht verwenden, weil SSL im Spiel ist uns es leider keinen SslSocketChannel gibt (nur eine kommerzielle Implementierung), und selber sowas schreiben kann ich nicht, dazu ist SslEngine zu kompliziert.

Der einzige Weg, den Thread zu beenden, der mir einfällt, ist den Socket zu schließen und im Thread auf eine Exception zu warten. Aber das erscheint mir alles andere als elegant ......

Hat jemand einen Hinweis, wie ich sinnvoll mit herkömmlichen Mitteln den select()-Aufruf simulieren kann? Oder einen anderen eleganten Weg, den Thread zu beenden?


Thomas


----------



## Guest (29. Aug 2007)

In Java 5 wurde eine SSLEngine eingeführt
www.onjava.com/pub/a/onjava/2004/11/03/ssl-nio.html
Vielleicht hilft dir das


----------



## thre (29. Aug 2007)

Hmm, ich sag ja, die API dieser Klasse ist mir zu kompliziert. Außerdem möchte ich lieber mit der "alten" I/O-Bibliothek arbeiten.


----------



## Guest (29. Aug 2007)

Am ende dews geposteten Artikels ist der komplette Code angehängt. Leichter gehts nicht mehr


----------



## thre (29. Aug 2007)

Trotzdem suche ich nach einer Möglichkeit, das Problem mit der klassischen I/O-Bibliothek zu lösen. Selbst wenn ich den Source komplett verwende, bläht der meinen Code nur unnötig auf. Außerdem habe ich schon seitenweise Code, den ich nicht auf NIO umstellen möchte.


----------



## sparrow (29. Aug 2007)

Sehe ich das richitig, dass es sich hierbei um den Thread handelt der auf dem Port lauscht und die eingehenden Verbindungen zur Bearbeitung weiter gibt?

Ich würde in dem Fall den Socket auch einfach schließen und dann in der Behandlung der Exception eine Statusvariable abrufen ob das Programm nun beendet werden soll oder ob dieser Fehler irgendwo anders aufgetreten ist. Soll das Programm beendet werden läuft der Thread aus, ansonsten wird der Socket wieder geöffnet.

Ich finde Exceptions sind nichts schlimmes, solange man sie nicht ignoriert.


Gruß
Sparrow


----------



## thre (29. Aug 2007)

Es ist eine Client-Applikation, es werden also keine eingehenden Verbindungen entgegengenommen, sondern die Verbindung besteht schon. Es handelt sich nur um einen Thread, der im Hintergrund arbeitet, um halt die GUI nicht zu blockieren.

Im Moment sieht mein Weg genau so aus, wie du ihn beschreibst. Ich finde es nur irgendwie unsauber. In der Vergangenheit haben wir nämlich auch schon die Erfahrungen mit manchen JVMs gemacht, dass im Worker-Thread nämlich keine Exception ausgelöst wurde, wenn der Socket aus einem anderen Thread heraus geschlossen wurde. Das war zwar ein Bug in der alten Netscape-JVM, aber wer garantiert, dass sowas nicht wieder passiert?

Naja, zur Not gibt's ja noch Thread.stop() ......


----------



## Guest (29. Aug 2007)

Thread.stop ist deprecated. Du solltest lieber Thread.interrupt benutzen


----------



## sparrow (29. Aug 2007)

Halt Moment, wenn das die Client-Seite ist, dann blockiert der Thread ja niemals (so wie es ein ServerSocket.accept() machen würde).
In diesem Fall ist es dann problemlos möglich innerhalb der run-Methode an Schlüsselstellen zu prüfen ob das intterupt-flag gesetzt wurde und dann den Thread sauber zu beenden (in den meisten Fällen bedeutet das, dass die Endlosschleife verlassen wird).


Thread.stop() sollte man unbedingt vermeiden da man keinerlei Eingriffsmöglichkeit mehr hat was der Thread beim beenden tut bzw. an welcher Stelle der Thread unterbroche wird.


----------



## thre (29. Aug 2007)

Der blockiert auch auf Client-Seite. Der hängt nämlich in einem read(). Das Protokoll ist so aufgebaut, dass der Client praktisch ständig auf irgendwelche Nachrichten vom Server wartet. Deshalb brauche ich ja das select(). Vielleicht hab ich das nicht richtig beschrieben.

Mir ist ja auch klar, dass Thread.stop() der letzte Ausweg ist. Ich schließe den Socket und hoffe, dass der Thread mit einer Exception aussteigt. Währenddessen wartet der Haupt-Thread mit Thread.join(1000) auf das Ende des Threads. Sollte er dann immer noch laufen (was eigentlich nicht sein dürfte), ziehe ich mit Thread.stop() den Stecker. Ein Thread.interrupt() würde an der Stelle wohl auch nicht mehr helfen.


Thomas


----------

