停止/销毁线程

问题描述

| 我有一个可以像这样启动线程和可运行对象的服务。
t = new Thread(new Runnable() {
    public void run() {
        doSomething();
    }
});

t.start();
@H_502_2@

该线程的原因是要执行异步任务doSomething()。现在,不用担心其他类AsyncTask。我已经尝试过了,但不适用于我的情况。编辑:我不能使用AsyncTask,因为它仅用于UI线程。这段代码必须在Service内部运行,所以没有,没有AsyncTask :(

doSomething()包含一些外部库,因此我遇到的问题是它可以潜在地挂在命令之一上,而无需返回任何值(因此甚至无法进行错误检查)

要变通解决此问题,我将在某个时间点销毁服务。

stopService(new Intent(\"net.MyService.intent));
@H_502_2@

这可以正常工作,并且可以在电话上轻松验证。但是,即使创建它的服务被销毁,上面创建的线程也将继续运行。

因此,我正在寻找要插入到Service \的onDestroy()中的正确命令,该命令将为我清理线程。

t.destroy();
t.stop();
@H_502_2@

都已贬值,并导致应用程序崩溃。

我从某处获取了这段代码

@Override
public void onDestroy() {

    Thread th = t;
    t = null;

    th.interrupt();

    super.onDestroy();
}
@H_502_2@

但是它仍然不起作用,线程继续运行。有帮助吗?
    


解决方法

线程
destroy
stop
本质上容易死锁并且不安全。它们的存在还给人一种幻觉,即当有其他人告诉别人时,可能会有某种方式立即停止另一个线程。 我理解您的想法,从您的角度来看,它们是一个主线程,并且当您想杀死它并重新启动它时,如果该线程在一段时间内未收到其工作线程的响应,关心它在做什么。但是不赞成使用这些方法的原因是您应该注意线程的作用。很多。 如果线程在您以后需要使用的变量周围具有锁,该怎么办?如果线程打开了文件句柄怎么办?在所有这些情况下,甚至更多的情况下,仅在当前操作中停止线程就会使事情变得一团糟-很可能您的应用程序会进一步崩溃。 因此,为了使线程可中断,可取消或可停止,它必须自己进行管理。如果线程或操作无法中断自身,则您将无法中断-假定这样做是不安全的。 如果你可以运行的话
public void run() {
   doSomething();
}
那么就没有办法打断它。有人希望,如果“ 7”是一个长时间的操作,可能会有一种方法与之交互,例如
public void run() {
   while (running) {
       MyParser.parseNext();
   }
}
或能够通过引用传递指示线程是否被中断的变量,并希望该方法可以在适当的位置中断自身。 请记住,ѭ9操作已被阻止。无法解决该问题,您无法部分取消它。     ,替代答案 使用以下代码:
MyThread thread;     // class field
立即创建并启动线程。
thread = new MyThread();
thread.start();
当服务被销毁时,“信号”线程退出
public void onDestroy() {
    // Stop the thread
    thread.abort = true;
    thread.interrupt();
}
这是线程实现
//another class or maybe an inner class
class MyThread extends Thread {
    syncronized boolean abort = false;

    //ugly,I know
    public void run() {
       try {
           if(!abort) doA();
           if(!abort) doB();
           if(!abort) doC();
           if(!abort) doD();
       } catch (InterruptedException ex) {
          Log.w(\"tag\",\"Interrupted!\");
       }
    }
}
您可能需要阅读以下内容: 您如何杀死Java中的线程? Claszen已经指出的线程原始弃用 http://www.devx.com/tips/Tip/31728-从这里基于我的代码,但是代码存在一些问题! 我认为您可以依靠捕获异常而不检查中止,但是我决定保持这种状态。 更新 我已经在codeguru中看到了以下示例:
public class Worker implements Runnable {
    private String result;
    public run() {
        result = blockingMethodCall();
    }
    public String getResult() {
        return result;
    }
}

public class MainProgram {
    public void mainMethod() {
        ...
        Worker worker = new Worker(); 
        Thread thread = new Thread(worker); 
        thread.start();
        // Returns when finished executing,or after maximum TIME_OUT time
        thread.join(TIME_OUT); 
        if (thread.isAlive()) {
            // If the thread is still alive,it\'s still blocking on the methodcall,try stopping it
            thread.interrupt();
            return null;
        } else {
            // The thread is finished,get the result
            return worker.getResult(); 
        }
    }
}
    ,您是否检查了Thread API JavaDoc中引用的Java Thread Primitive Deprecation文档。您会发现一些提示来解决您的问题。     ,为什么不使用AsyncTask?   可以通过以下方式随时取消任务   调用cancel(boolean)。调用中   此方法将导致后续   调用isCancelled()返回true。   调用此方法后,   onCancelled(Object),而不是   onPostExecute(Object)将被调用   在doInBackground(Object [])之后   返回。确保任务是   尽快取消,您   应该经常检查返回值   的isCancelled()的周期   如果可能,请执行doInBackground(Object [])   (例如在循环内。)     ,我喜欢采用以下方法:
class MyHandler extends Handler {
    final Semaphore stopEvent = new Semaphore(0);

    @Override
    public void handleMessage(Message msg) {
        try {
            while (!stopEvent.tryAcquire(0,TimeUnit.SECONDS)) {
                doSomething();

                if (stopEvent.tryAcquire(SLEEP_TIME,TimeUnit.MILLISECONDS)) {
                    break;
                }
            }
        } catch (InterruptedException ignored) {
        }

        stopSelf();
    }
}
在服务onDestroy上,只需释放stopEvent即可:
@Override
public void onDestroy() {
    myHandler.stopEvent.release();
    myHandler = null;

    super.onDestroy();
}
    ,最好使用全局变量stopThread,一旦变量更改为true,就停止线程。
btnStop.setOnClickListener(new OnClickListener() {          
        @Override
        public void onClick(View arg0){
            stopThread = true;
        }
    }); 


public void run() {
        while (!stopThread) {
           //do something
        }
}
    ,我认为创建和与另一个线程通信的最佳方法是使用AsyncTask。这里是一个例子:
public class Task extends AsyncTask<Void,Void,Void> {

    private static final String TAG = \"Task\";

    private boolean mPaused;

    private Runnable mRunnable;

    public Task(Runnable runnable) {
        mRunnable = runnable;
        play();
    }

    @Override
    protected Void doInBackground(Void... params) {
        while (!isCancelled()) {
            if (!mPaused) {

                mRunnable.run();
                sleep();
            }
        }
        return null;
    }

    private void sleep() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            Log.w(TAG,e.getMessage());
        }
    }

    public void play() {
        mPaused = false;
    }

    public void pause() {
        mPaused = true;
    }

    public void stop() {
        pause();
        cancel(true);
    }

    public boolean isPaused() {
        return mPaused;
    }

}
现在,您可以轻松使用此类,并通过编写以下内容启动线程:
Task task = new Task(myRunnable);
task.execute((Void) null);
除此之外,您还可以轻松地暂停或停止线程循环: 暂停和播放线程的示例:
mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (task.isPaused()) {
            task.play();
        } else {
            task.pause();
        }
    }
});
停止和启动线程的示例:
mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (task.isCancelled()) {
            task = new Task(myRunnable);
            task.execute((Void) null);
        } else {
            task.stop();
        }
    }
});