【问题标题】:Android thread in service issue服务问题中的Android线程
【发布时间】:2011-07-30 15:45:31
【问题描述】:

我正在运行一个远程服务,其中我正在生成一个新线程以继续轮询通过套接字传入的消息,然后每隔一段时间我想停止套接字并稍后重新启动...停止工作正常(stopUARTConnection( )) 但重新启动(startUARTConnection) 不会再次导致 while 循环。有人可以告诉我有什么问题吗?

public class BackgroundService extends Service{

ServerSocket server = null;
Socket socketClient = null;
InputStream is = null;
BufferedReader br = null;
char[] buff = null;
boolean threadRunning = true;

private static final String TAG = BackgroundService.class.getSimpleName();
private Thread socketThread = null;
int temp = 0;

@Override
public IBinder onBind(Intent intent) {
    if (BackgroundService.class.getName().equals(intent.getAction())) {
        Log.d(TAG, "Bound by intent " + intent);
        return apiEndpoint;
    } else {
        return null;
    }
}

private final Object latestIncomingMessage = new Object();
private List<MessageCollectorListener> listeners = new ArrayList<MessageCollectorListener>();
private Message message = new Message(" ");

private MessageCollectorApi.Stub apiEndpoint = new MessageCollectorApi.Stub() {
    @Override
    public void removeListener(MessageCollectorListener listener) throws RemoteException {
        synchronized (listener) {
            listeners.remove(listener);
        }
    }

    @Override
    public Message getValue() throws RemoteException {
        synchronized (latestIncomingMessage) {
            return message;
        }
    }

    @Override
    public void addListener(MessageCollectorListener listener) throws RemoteException {
        synchronized (listener) {
            listeners.add(listener);
        }
    }

    @Override
    public void startBroadCastConn() throws RemoteException {
        try {
            startUARTConnection();
        } catch (IOException e) {
            Log.d("B Service", "Stop UART CONNECTION");
        }

    }

    @Override
    public void stopBroadCastConn() throws RemoteException {
        try {
            stopUARTConnection();
        } catch (IOException e) {
            Log.d("B Service", "Stop UART CONNECTION");
        }           
    }
};

public boolean createSocket(int port) {
    try{
        server = new ServerSocket(port);
    } catch (IOException e) {
        return false;
    }
    return true;
}

public boolean listenSocket(){
    try{
        socketClient = server.accept();
    } catch (IOException e) {
        return false;
    }
    return true;
}

@Override
public void onCreate() {
    super.onCreate();
    socketThread = new Thread(){
        @Override
        public void run() {
            while(threadRunning){
                boolean socketCreated = createSocket(8080);
                boolean socketListen = listenSocket();
                if(socketListen == true && socketCreated == true){
                    //To add code for processing data..
                    threadRunning = true;
                }
                try {
                    recycle();
                } catch (IOException e) {
                    //e.printStackTrace();
                }
            }
        }   
    };
    socketThread.start();
}
public void stopUARTConnection() throws IOException{
    recycle();
    threadRunning = false;
}

public void startUARTConnection() throws IOException{
    recycle();
    threadRunning = true;
}

private void recycle() throws IOException{
    if(socketClient != null){
        socketClient.close();
        socketClient = null;
    }   
    if(is != null)
        is.close();
    if(server != null){
        server.close();
        server = null;
    }
}

@Override
public void onDestroy() {
    super.onDestroy();
    try {
        recycle();
    } catch (IOException e) {
        Log.d("B Service", "Failed to recycle all values");
    }
    socketThread = null;
}

}

【问题讨论】:

    标签: android


    【解决方案1】:

    当您调用 stopUARTConnection 时,您正在设置 threadRunning=false...此时,您的 while 循环正在退出...在 startUARTConnection 中,您将 threadRunning 设置为 true,但您没有重新启动线程。

    正如@Marvin 指出的,you can't just call start on the thread object,您需要重新创建它。

    【讨论】:

    • -1 因为您无法启动已经启动过一次的线程。第二次调用 startUARTConnection 时会抛出 IllegalThreadStateException。
    • 听说我必须在重新开始之前销毁该线程..我们可以通过分配 thread = null 来销毁吗? ???
    • @Arun Abraham:请参阅 Marvin 的回复。您不必销毁线程(它会退出),您可以在现有引用上创建一个新的
    • @MarvinLabs:感谢您的指点。我不知道您无法重新启动线程对象,我假设它进入退出状态就可以了。我想这不是我需要做的事情,通常如果我启动一个线程,我不希望在应用程序准备退出之前将其关闭。
    • 始终明确关闭您启动的线程,否则它们将继续在后台运行,您会泄漏内存...
    【解决方案2】:

    您只创建一次线程。因此,循环只运行一次,直到被指示退出。

    public void startUARTConnection() throws IOException{
        recycle();
        socketThread = new SocketThread();
        socketThread.start();
    }
    
    public void stopUARTConnection() throws IOException{
        recycle();
        socketThread = null;
    }
    
    private class SocketThread extends Thread {
        @Override
        public void run() {
            // Loop until socketThread is assigned something else 
            // (a new Thread instance or simply null)
            while (socketThread==this){
                boolean socketCreated = createSocket(8080);
                boolean socketListen = listenSocket();
                if(socketListen == true && socketCreated == true){
                    // To add code for processing data..
                }
                try {
                    recycle();
                } catch (IOException e) {
                    //e.printStackTrace();
                }
            }
        }   
    };
    

    【讨论】:

    • hmmm...看起来不错...但是我们是否应该在重新开始之前销毁线程...我应该将线程分配给 null 来执行它吗?
    • socketThread==this 会检测到你创建了一个新的 SocketThread,然后旧的 Thread 会退出。如果您需要确保没有同时运行 2 个线程,则需要基于 join() 实施检查。
    • 嘿....非常感谢...您的解决方案是正确的..非常感谢..对线程真的很陌生...:)
    • @Arun Abraham:如果马文解决了你的问题,你真的应该接受这个答案......
    【解决方案3】:

    我认为最好使用 TimerTask 而不是 thread/while 和 ConditionVariable 而不是布尔变量 threadRunning

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多