Frage zu Threads

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Frage zu Threads

    Hallo,
    ich habe bisher wenig Java Erfahrung, und bin mir nicht sicher, ob ich nicht was falsch gemacht habe.

    Ich habe eine Main Activity mit einem onClickListener für einen Button.
    Wenn der Button geklickt wird, möchte ich ein kurzes Textkommando per TCP/IP versenden.
    Dazu erzeuge ich im onClickListener einen TcpSender - Thread, übergebe im "Konstruktor" den zu sendenden Text, und der Thread sendet den Text dann.
    Das funktioniert zwar scheinbar, aber ich bin nicht sicher, ob das so richtig programmiert ist.

    Zunächst mal die relevanten Code-Teile (nur das Wesentliche !!!)

    Ausschnitt aus der MainActivity:

    Quellcode

    1. @Override
    2. public void onClick ( View v )
    3. {
    4. new Thread ( new com.bernd.demo.TcpSender( "HALLO" ) ).start ( );
    5. }


    Und hier Ausschnitte vom Sende-Thread:

    Quellcode

    1. public class TcpSender implements Runnable
    2. {
    3. String url = MY_URL;
    4. int portNumber = MY_PORT;
    5. Socket tcpSocket;
    6. PrintWriter msgWriter;
    7. String msgToSend;
    8. public TcpSender( String strParam )
    9. {
    10. // keep string to send for the run-method
    11. msgToSend = strParam;
    12. }
    13. @Override
    14. public void run ( )
    15. {
    16. try
    17. {
    18. // create a TCP/IP socket
    19. tcpSocket = new Socket ( url, portNumber );
    20. // create a printwriter (with auto-flush) and assign to the socket
    21. msgWriter = new PrintWriter ( tcpSocket.getOutputStream(), true );
    22. // send message to server
    23. msgWriter.println ( msgToSend );
    24. // close Printwriter and TCP/IP socket
    25. msgWriter.close ( );
    26. tcpSocket.close ( );
    27. }
    28. catch (IOException e)
    29. {
    30. Log.d ( LOG_TAG, "IO Exception" );
    31. }
    32. }
    33. }
    Alles anzeigen
    Jetzt meine Fragen:
    1. Im onClickListener erzeuge ich doch eigentlich bei jeden Button-Klick eine neue Instanz vom TcpSender-Thread.
    Müsste man den erzeugten Thread nicht einer Variablen zuweisen, und diese wieder zerstören? Wenn ja wo und wann?
    Oder erzeuge ich da einen riesigen Stapel von Threads und mülle meinen Speicher mit Thread-Leichen voll?

    2. Wie ist das mit der Run-Methode im Thread. Ich sende da was und dann?
    Wird die Run-Methode nach dem Senden beendet?
    Wenn sie beendet wird, ist dann auch das Thread-Objekt automatisch zerstört ? (das wäre die Antwort auf Frage 1)

    3. Könnte der Thread theoretisch schon zerstört werden, WÄHREND oder BEVOR die Daten komplett gesendet wurden?

    Vielen Dank im Voraus
  • 1.

    Korrekt du erzeugst immer einen neuen Thread bei Klick.
    Dadurch erzeugst ggfs. viele Threads, aber da du sie keiner Variable zuweist, werden Sie vom Garbage Collector aufgeräumt/gelöscht.


    2.

    Siehe Antwort 1.
    Der Garbage Collector räumt den Thread weg, wenn er nicht mehr genutzt wird.

    3.

    Ja, allerdings musst du den Thread selbst stoppen/zerstören.
    Falls du den Thread stoppst und es laufen noch Operationen wird eine InterruptedException geworfen.


    Noch ein Tipp.
    Aktuell wird bei jedem Klick eine neue Verbindung zum Socket aufbaust. Klickst du also 5x werden 5x Verbindungen aufgebaut, Daten übertragen und die Verbindung beendet,
    Im Optimalfall sollte man versuchen die Verbindung zu halten, falls noch mehr Daten erwartet. Da es je nach Datenmenge schon Performance-Probleme geben kann, wenn du jedes mal die Verbindung neu aufbauen musst.
    (Kenne deinen genauen Usecase jetzt nicht)

  • Danke für deine Antwort.
    Das Ganze ist eine Torsteuerung für ein Carport (elektrisches Rolltor).
    Ich sende immer auf Buttonklick kurze TCP/IP Kommandos ( Tor hoch, Tor runter u.s.w.).
    Wenn die Verbindung nach dem Kommando wieder weg ist, macht das nichts, bzw ist das so gewollt.

    Wenn ich das richtig verstehe, wäre also der richtige Weg so:
    In der Run-Methode des Thread warten, bis das Kommando gesendet wurde und dann den Thread am Ende der Run Methode beenden?

    Merkwürdig nur:
    Der momentane Ablauf in der Run Methode ist ja so:
    Text senden
    Socket schließen.
    Run Methode beenden

    Wenn das Kommando noch nicht gesendet wurde, würde doch schon beim Schließen des Socket was schieflaufen?
    Tut es aber nicht.
    Also gehe ich mal davon aus, wenn ich den Socket schließe ist alles gesendet.

    Dann wäre nur die Frage: Wie den Thread am Ende der Run Methode beenden, damit er aus dem Speicher entfernt wird.
  • Also ich habe das jetzt mal ausgiebig getestet.
    Die TCP/IP Kommandos (Tor auf, Tor zu) werden immer korrekt und vollständig gesendet.

    Wenn man nach Infos sucht, wie man einen Thread beendet, findet man nur Antworten, wie das von aussen geht (dort, wo er erzeugt und gestartet wird).
    Ich möchte allerdings, das sich der Thread selbst nach getaner Arbeit (senden eines einzelnen Kommandos) beendet und aus dem Speicher entfernt.
    Was wäre denn, wenn ich den in der Main-Activity erzeugten Thread einer Thread-Variablen zuweise?
    Würde er dann beendet und entfernt, wenn ich die Run-Methode mit return; verlasse?
    Oder geht das anders?
    Wie?
  • Hallo wenn du nur die zwei Befehle senden willst würde ich es so lassen wie es war.

    Du brauchst den Thread nicht selber beenden. Der beendet sich selber. Wen die Run Methode durlaufen ist und das ist auch so wenn die Verbindung abbricht und du in dem Catch Block ankommst danach ist der Thread bei dir beendet.

    Ein beenden eines Threads von außen würde zb bei einer Endlosschleife im Thread Sinn machen notwendig sein. In deinem Fall nicht.


    Das scheinst du etwas falsch verstanden zu haben.

    Auch ist es egal ob du dem Thread eine Variablegibst die auf das Objekt zeigst oder nicht, wenn der Thread beendet ist wird das Objekt auch aus den Speicher gelöscht. Das wirst du aber auch nicht unbedingt sofort sehen können . Das macht der GC wenn er dafür zeit hat oder de Speicher wirklich sehr stark voll ist. Dann werden nicht mehr benutzte Elemente gelöscht. Aber das Thema hatten wir ja schon mal.


    Der Punkt 1. von meinen Vorredner ist so also nicht ganz richtig. ob eine Variable benutzt wird oder nicht ist egal.
    intern wird immer ein Objekt erstllt und der GC hatt das unter kontrolle.

    Zum Thema beenden eine Threads von außen dazu würdest du das Objekt brauchen also eine Variable .


    Was wäre denn, wenn ich den in der Main-Activity erzeugten Thread einer Thread-Variablen zuweise?
    Würde er dann beendet und entfernt, wenn ich die Run-Methode mit return; verlasse?


    Ein Return in der run Methode würde ein internes beenden bedeuten.

    Beenden von außen dazu brachst du das Objekt also eine Variable und dann nicht .start() sondern .stop() .

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von nono124 ()