2009-07-30 93 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 2009-07-31 21:34:55

11

問題是您的線程需要合作,定期檢查中斷並在線程中斷時退出。除非你在線程中沿着以下幾行放置東西......

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

......你的線程將會忽略它已被中斷的事實。 Lucas S.提出的方法基本上是相同的,只是如果線程被阻塞,使用中斷將產生一個異常,而在Lucas S.的方法下,您可能必須無限期地等待線程退出。