java intentservice详解 - 在哪里停止/销毁Android服务类中的线程?




1 Answers

附录 :Android框架为一次性工作,后台工作等提供了许多帮助,这可能比在许多情况下尝试滚动自己的线程更可取。 如下文所述,AsyncTask是一个很好的起点。 我鼓励读者在开始考虑做自己的线程之前先研究框架规定。

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

1)Thread.stop()已经被弃用了很长一段时间,因为在某些情况下它可能会使因变量处于不一致状态。 有关更多详细信息,请参阅此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
  }
}

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

2)您的测量列表可以由多个线程(事件线程和您的用户线程)同时访问,无需任何同步。 看起来您不必滚动自己的同步,您可以使用BlockingQueue

3)您在发送线程的每次迭代中创建一个新的Socket。 这是一项相当重要的操作,只有在您希望测量非常罕见(比如一小时或更短时间)时才真正有意义。 要么你想要一个不会在线程的每个循环中重新创建的持久套接字,要么你想要一次性运行,你可以“触发并忘记”创建套接字,发送所有相关数据并完成。 (关于使用持久性Socket的快速说明,阻塞的套接字方法,如读取,不能被Thread.interrupt()中断,所以当你想要停止线程时,你必须关闭套接字以及调用中断)

4)除非你希望在其他地方捕获它,否则从Thread中抛出你自己的异常几乎没有意义。 更好的解决方案是记录错误,如果不可恢复,请停止该线程。 一个线程可以使用代码(在与上面相同的上下文中)自行停止:

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

最后,如果你想确定一个线程退出你的应用程序的其余部分,无论如何,一个好的技术是在创建之后和启动线程之前调用Thread.setDaemon(true)。 这会将线程标记为守护程序线程,这意味着如果没有运行非守护程序线程(例如,如果您的应用程序退出),VM将确保自动销毁它。

关于线程的服从最佳实践应确保您的应用程序不会挂起或放慢手机,尽管它们可能非常复杂:)

intentservice注册 android多线程

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

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

...
}

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

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




Related