2009-07-30 99 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.的方法下,您可能必须无限期地等待线程退出。