为什么线程不停止?

Why isn't the thread stopping?

提问人:montooner 提问时间:7/30/2009 更新时间:7/30/2009 访问量:22167

问:

我的服务生成一个新线程,并根据通常推荐的 java 方法 interrupt()'ing 停止它。当我停止服务时,我在 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());
        }
    }
        }
Android 多线程

评论


答:

0赞 Prashast 7/30/2009 #1

中断线程会在线程中引发异常,它不一定会停止它。您应该捕获该异常,然后在退出之前在线程中进行清理(前提是,您需要退出!

评论

0赞 Fredrik 8/1/2009
实际上,它不会引发异常。如果某些调用检测到它们已被中断,它们会抛出异常,但在大多数情况下,您必须通过检查 Thread.isInterrupted() 来自己进行检测,何时适合中断工作。
13赞 Lucas S. 7/30/2009 #2

我认为最安全的方法是有一个标志,以便线程在其主循环中检查它。

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;
    }
}
11赞 Michael Aaron Safyan 7/30/2009 #3

问题在于,您的线程需要通过定期检查中断来协作,如果线程被中断,则退出。除非您在线程中放置类似以下内容的内容......

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

...您的线程将忽略它已被中断的事实。Lucas S. 提出的方法基本相同,只是如果线程被阻塞,使用中断将产生异常,而在 Lucas S. 的方法下,您可能需要无限期地等待线程退出。