在哪里停止/销毁Android服务类中的线程?

我已经通过以下方式创build了一个线程服务:

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); } } } ... } 

closures应用程序后,手机工作非常慢,我想这是由于线程终止失败。

有没有人知道什么是在终止应用程序之前终止所有线程的最佳方法?

附录 :Android框架为一次性工作,后台工作等提供了许多帮助,这可能比尝试在许多情况下推出自己的线程更可取。 正如在下面的post中提到的,AsyncTask是一个很好的开始。 我鼓励读者在开始考虑自己的线程之前先看看框架条款。

您发布的代码示例中有几个问题,我将按顺序解决:

1)Thread.stop()现在已经被弃用了很长一段时间,因为在某些情况下它可以使依赖variables处于不一致的状态。 有关更多详细信息,请参阅此Sun答案页 (编辑:该链接现已停用,请参阅此页面,以便不使用Thread.stop() )。 停止和启动一个线程的首选方法如下(假设你的线程将无限期运行):

 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 } } 

这只是一个例子,如何停止线程,但外卖是你负责退出一个线程,就像你的任何其他方法。 维护一个跨线程通信的方法(在这种情况下,一个volatilevariables,也可以通过互斥体等),并在你的线程逻辑中,使用这种通信方法来检查你是否应该提前退出,清理等。

2)您的测量列表是由多个线程(事件线程和您的用户线程)在同一时间访问,没有任何同步。 它看起来像你不必滚动自己的同步,你可以使用BlockingQueue 。

3)你正在创build一个新的套接字每发送一次线程。 这是一个相当重量级的操作,只有当您期望测量非常less(比如说一个小时或更less)时才真正有意义。 要么你想要一个持久的套接字,而不是在线程的每一个循环中重新创build,或者你想要一个可以运行的套接字,你可以“发送并忘记”它创build套接字,发送所有相关的数据,并完成。 (有关使用持久化Socket的简要说明,socket的方法(如read,block等)不能被Thread.interrupt()中断,所以当你想要停止线程时,必须closures套接字以及调用中断)

4)除非你希望在别的地方捕捉它,否则从Thread中抛出你自己的exception是没有意义的。 一个更好的解决scheme是logging错误,如果它是不可恢复的,停止线程。 一个线程可以像代码一样停止自己(在上面的相同的上下文中):

 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 } } } 

最后,如果你想要确保一个线程退出其余的应用程序,不pipe怎么样,一个好的技术是在创build之后和启动线程之前调用Thread.setDaemon(true)。 这将线程标记为守护程序线程,这意味着如果没有非守护线程正在运行(例如,如果您的应用程序退出),VM将确保它自动销毁。

遵守有关线程的最佳做法应确保您的应用程序不会挂起或放慢电话,尽pipe它们可能相当复杂:)

其实,你不需要上面描述的“runner”variables,就像:

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

但通常,坐在Thread.sleep()循环中是一个非常糟糕的主意。

查看新的1.5 API中的AsyncTask API。 它可能会比使用服务更优雅地解决你的问题。 您的手机正在变慢,因为服务从未closures – 没有任何事情会导致服务自杀。