Reputation: 1132
My service spawns a new thread, and stops it according to the typically recommended java method of interrupt()'ing. When I stop the service, I stop the thread in onDestroy(). The service is stopped, and the interrupt code is reached. However, soon enough the thread restarts from the beginning of the Runnable.
public class DoScan extends Service {
public volatile Thread runner;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
startThread();
}
@Override
public void onDestroy() {
super.onDestroy();
android.util.Log.v("@@@@@@@@@@@@@@@@@@@@", "DoScan.onDestroy");
stopThread();
}
public synchronized void startThread(){
if(runner == null){
android.util.Log.v("@@@@@@@@@@@@@@@@@@@@", "DoScan.startthread");
runner = new Thread(new ScanningThread());
runner.start();
}
}
/* use a handler in a loop cycling through most of oncreate.
* the scanningthread does the work, then notifies the svc's uithread
*/
public synchronized void stopThread(){
if(runner != null){
android.util.Log.v("@@@@@@@@@@@@@@@@@@@@", "DoScan.stopthread");
Thread moribund = runner;
runner = null;
moribund.interrupt();
android.util.Log.v("@@@@@@@@@@@@@@@@@@@@", "interrupted?" + moribund.isInterrupted());
}
}
}
Upvotes: 5
Views: 22169
Reputation: 95509
The problem is that your thread needs to cooperate by periodically checking for interruption and exiting if the thread has been interrupted. Unless you place something along the lines of the following in your thread...
// Processing... if ( Thread.interrupted() ){ return; } // More processing... try{ Thread.sleep(sleeptime); }catch(InterruptedException interrupt){ return; } // Rinse and repeat...
...your thread will just ignore the fact that it has been interrupted. The method proposed by Lucas S. is essentially identical, except that using interruption will generate an exception if the thread is blocked, whereas under Lucas S.'s method, you might have to wait indefinitely for the thread to quit.
Upvotes: 11
Reputation: 13541
I think the safest way is to have a flag so the thread checks for it inside its main loop.
class ScanningThread extends Thread {
// Must be volatile:
private volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println("alive");
}
if (stop)
System.out.println("Detected stop");
}
public synchronized void requestStop() {
stop = true;
}
}
public synchronized void startThread(){
if(runner == null){
android.util.Log.v("@@@@@@@@@@@@@@@@@@@@", "DoScan.startthread");
runner = new ScanningThread();
runner.start();
}
}
public synchronized void stopThread(){
if(runner != null){
android.util.Log.v("@@@@@@@@@@@@@@@@@@@@", "DoScan.stopthread");
runner.requestStop();
runner = null;
}
}
Upvotes: 13
Reputation: 5675
Interrupting a thread throws an exception in the thread, it does not necessarily stop it. You should catch that exception and then do the clean up in thread before exiting (provided, you need to exit!).
Upvotes: 0