Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the thread stopping?

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());
        }
    }
        }
like image 810
montooner Avatar asked Jul 30 '09 01:07

montooner


2 Answers

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;
    }
}
like image 83
Lucas S. Avatar answered Sep 19 '22 23:09

Lucas S.


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.

like image 34
Michael Aaron Safyan Avatar answered Sep 20 '22 23:09

Michael Aaron Safyan