2009-07-30 21 views
3

私のサービスは新しいスレッドを生成し、interrupt()のメソッドtypically recommended javaに従ってそれを停止します。サービスを停止すると、onDestroy()のスレッドが停止します。サービスが停止され、割り込みコードに達する。しかし、すぐにスレッドは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()); 
     } 
    } 
     } 

答えて

11

スレッドがメインループ内でそれをチェックするようにフラグを設定するのが最も安全な方法だと思います。

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

スレッドを中断すると、スレッド内で例外がスローされますが、必ずしもスレッドを停止するとは限りません。その例外をキャッチしてから、終了する前にスレッドでクリーンアップを実行する必要があります(ただし、終了する必要があります)。

+0

実際には例外は発生しません。中断されたことが検出された場合、一部の呼び出しは例外を戻しますが、ほとんどの場合、作業を中断するのに適したThread.isInterrupted()をチェックして、自分で検出を行う必要があります。 – Fredrik

11

問題は、スレッドが中断されていないかどうかを定期的に確認し、スレッドが中断された場合に終了する必要があることです。あなたのスレッドに次の行に沿って何かを配置しない限り...

 
// Processing... 
if (Thread.interrupted()){ 
    return; 
} 
// More processing... 
try{ 
    Thread.sleep(sleeptime); 
}catch(InterruptedException interrupt){ 
    return; 
} 
// Rinse and repeat... 

...あなたのスレッドは、中断されたという事実を無視します。 Lucas S.が提案した方法は基本的には同じですが、スレッドをブロックすると例外が発生するのに対し、Lucas S.の方法ではスレッドを無期限に待たなければならない場合があります。

関連する問題