Wo zu stoppen / zerstören Threads in Android Service-Klasse?

Ich habe einen Thread-Service auf folgende Weise erstellt:

public class TCPClientService extends Service{ ... @Override public void onCreate() { ... Measurements = new LinkedList<String>(); enableDataSending(); } @Override public IBinder onBind(Intent intent) { //TODO: Replace with service binding implementation return null; } @Override public void onLowMemory() { Measurements.clear(); super.onLowMemory(); } @Override public void onDestroy() { Measurements.clear(); super.onDestroy(); try { SendDataThread.stop(); } catch(Exception e){ ... } } private Runnable backgrounSendData = new Runnable() { public void run() { doSendData(); } }; private void enableDataSending() { SendDataThread = new Thread(null, backgrounSendData, "send_data"); SendDataThread.start(); } private void addMeasurementToQueue() { if(Measurements.size() <= 100) { String measurement = packData(); Measurements.add(measurement); } } private void doSendData() { while(true) { try { if(Measurements.isEmpty()) { Thread.sleep(1000); continue; } //Log.d("TCP", "C: Connecting..."); Socket socket = new Socket(); socket.setTcpNoDelay(true); socket.connect(new InetSocketAddress(serverAddress, portNumber), 3000); //socket.connect(new InetSocketAddress(serverAddress, portNumber)); if(!socket.isConnected()) { throw new Exception("Server Unavailable!"); } try { //Log.d("TCP", "C: Sending: '" + message + "'"); PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true); String message = Measurements.remove(); out.println(message); Thread.sleep(200); Log.d("TCP", "C: Sent."); Log.d("TCP", "C: Done."); connectionAvailable = true; } catch(Exception e) { Log.e("TCP", "S: Error", e); connectionAvailable = false; } finally { socket.close(); announceNetworkAvailability(connectionAvailable); } } catch (Exception e) { Log.e("TCP", "C: Error", e); connectionAvailable = false; announceNetworkAvailability(connectionAvailable); } } } ... } 

Nachdem ich die Anwendung beendet habe, funktioniert das Telefon wirklich langsam und ich denke, es ist wegen Fix-Terminierungsfehler.

  • R kann bei der Verwendung von ActionBarSherlock nicht behoben werden
  • Android: View.getTag / setTag und IllegalArgumentException
  • Xamarin.Android - macht native Code Compilation Reverse Engineering härter?
  • Android Expandable RecyclerAlle Kartenhöhe anzeigen
  • Android Launcher Icon Rounded Corner Edge Radii
  • Samsung Galaxy s2 DSR ist eingeschaltet. Nicht gesendet DTR ON
  • Weiß jemand, was ist der beste Weg, um alle Threads zu beenden, bevor Sie die Anwendung beenden?

  • Aufruf von setVolumeControlStream von einem Service
  • Machen Sie Popup der Taste in einer angepassten Tastatur gedrückt
  • Erstellen Sie den UI-Thread manuell in Android, um seine kleine Stack-Größe zu erhöhen
  • Probleme beim Verbinden mit Bluetooth Android
  • Wie man die rufende Aktivität in android kennt
  • Android - wie man eine Abzeichenzählung zu einem Anwendungssymbol hinzufügen kann?
  • 2 Solutions collect form web for “Wo zu stoppen / zerstören Threads in Android Service-Klasse?”

    Addendum : Das Android-Framework bietet viele Helfer für einmalige Arbeit, Hintergrundarbeit, etc., was vorzuziehen ist, wenn man versucht, Ihren eigenen Thread in vielen Fällen zu rollen. Wie in einem unten stehenden Post erwähnt, ist AsyncTask ein guter Ausgangspunkt, um hineinzuschauen. Ich ermutige die Leser, zuerst die Rahmenbestimmungen zu betrachten, bevor sie anfangen, darüber nachzudenken, dass sie ihr eigenes Threading machen.

    Es gibt mehrere Probleme in der Code-Probe, die Sie gepostet haben, werde ich in der Reihenfolge:

    1) Thread.stop () ist seit geraumer Zeit veraltet, da es unter bestimmten Umständen abhängige Variablen in inkonsistente Zustände verlassen kann. Sehen Sie diese Sun-Antwort-Seite für weitere Details (Bearbeiten: dieser Link ist jetzt tot, siehe diese Seite für warum nicht zu verwenden Thread.stop () ). Eine bevorzugte Methode zum Stoppen und Starten eines Threads ist wie folgt (vorausgesetzt, Ihr Thread läuft etwas unendlich):

     private volatile Thread runner; public synchronized void startThread(){ if(runner == null){ runner = new Thread(this); runner.start(); } } public synchronized void stopThread(){ if(runner != null){ Thread moribund = runner; runner = null; moribund.interrupt(); } } public void run(){ while(Thread.currentThread() == runner){ //do stuff which can be interrupted if necessary } } 

    Dies ist nur ein Beispiel dafür, wie man einen Thread zu stoppen, aber das Essen ist, dass Sie dafür verantwortlich sind, einen Thread zu beenden, so wie Sie es irgendeine andere Methode hätten. Halten Sie eine Methode der Cross-Thread-Kommunikation (in diesem Fall eine flüchtige Variable, könnte auch durch eine Mutex, etc.) und innerhalb Ihrer Thread-Logik, verwenden Sie diese Methode der Kommunikation zu überprüfen, ob Sie frühzeitig verlassen, bereinigen, etc.

    2) Auf Ihre Messungsliste wird durch mehrere Threads (der Event Thread und Ihr User Thread) gleichzeitig ohne Synchronisation zugegriffen. Es sieht so aus, als hättest du keine eigene Synchronisation zu rollen, du kannst eine BlockingQueue verwenden .

    3) Du schaffst eine neue Socket jede Iteration deines sendenden Thread. Dies ist eine ziemlich schwere Operation, und nur wirklich sinnvoll, wenn Sie erwarten, dass Messungen extrem selten (sagen Sie eine Stunde oder weniger). Entweder du willst eine anhaltende Steckdose, die nicht jede Schleife des Threads neu erstellt wird, oder du willst einen Schuss, den du kannst, kannst du "feuern und vergessen", der eine Sockel schafft, alle relevanten Daten sendet und beendet. (Eine kurze Notiz über die Verwendung eines persistenten Sockets, Socket-Methoden, die blockieren, wie das Lesen, kann nicht durch Thread.interrupt () unterbrochen werden, und so, wenn Sie den Thread stoppen möchten, müssen Sie den Sockel schließen und den Interrupt aufrufen)

    4) Es gibt wenig Sinn, deine eigenen Ausnahmen aus einem Thread zu werfen, es sei denn, du erwartest, es irgendwo anders zu fangen. Eine bessere Lösung ist, den Fehler zu protokollieren und wenn es uneinbringlich ist, stoppen Sie den Thread. Ein Thread kann sich mit Code wie (im gleichen Zusammenhang wie oben) stoppen:

     public void run(){ while(Thread.currentThread() == runner){ //do stuff which can be interrupted if necessary if(/*fatal error*/){ stopThread(); return; //optional in this case since the loop will exit anyways } } } 

    Schließlich, wenn Sie sicher sein wollen, dass ein Thread mit dem Rest Ihrer Anwendung verlässt, egal was, eine gute Technik ist, Thread.setDaemon (true) nach der Erstellung anzurufen und bevor Sie den Thread starten. Dies markiert den Thread als Daemon-Thread, was bedeutet, dass die VM sicherstellt, dass sie automatisch zerstört wird, wenn es keine Nicht-Daemon-Threads gibt (z. B. wenn deine App beendet wird).

    Befolgen von Best Practices in Bezug auf Threads sollte sicherstellen, dass Ihre App nicht hängt oder verlangsamt das Telefon, obwohl sie ziemlich komplex sein können 🙂

    Eigentlich brauchst du nicht die "Läufer" Variable wie oben beschrieben, so etwas wie:

     while (!interrupted()) { try { Thread.sleep(1000); } catch (InterruptedException ex) { break; } } 

    Aber im Allgemeinen sitzt in einer Thread.sleep () Schleife eine wirklich schlechte Idee.

    Schauen Sie sich die AsyncTask API in der neuen 1.5 API an. Es wird wahrscheinlich Ihr Problem eleganter lösen als mit einem Service. Ihr Telefon wird langsam, weil der Service nie heruntergefahren wird – da ist nichts, was dazu führt, dass der Service sich selbst tötet.

    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.