在Android应用程序中多次调用Thread.interrupt,但我只调用一次

时间:2015-03-18 19:46:09

标签: java android multithreading

这个问题实际上只是出于纯粹的好奇心。我已经找到了一个解决方法,如果有人有兴趣,我会在问题的最后解释。

我有一个运行后台线程的Android应用程序。我想在用户按下电源键时中断该线程。为了实现这一点,我使用了这样的BroadcastReceiver:

public Class MyService extends Service {
  private MyThread myThread;

  //https://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
  private class ScreenReceiver extends BroadcastReceiver {

      boolean wasScreenOn = true;

      @Override
      public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            Log.d(TAG, "Power key!");
            myThread.interrupt();
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            wasScreenOn = true;
        }
      }

  }
  private Class MyThread extends Thread {
    private MyObject myObject;
    //various thread functions
    public void run(){
      while(!isInterrupted()){
        //I have code here that waits for the user to let us know to start
        myObject = new MyObject();
        myObject.foo();
      }
    }
  }

  public void onCreate(){
    //various setup steps
    myThread = new MyThread();
    myThread.start(); //myThread.run() will get called by this
  }
}

不幸的是,仅仅中断线程是不够的,因为它不会频繁地轮询中断:线程包含一个对象(MyObject)的实例,它正在运行一个函数(foo),我可以' t轮询线程上的中断,直到foo完成。为了解决这个问题,我在MyObject类中实现了一个标志,我可以在foo中检查并在必要时中断函数(就像Thread.interrupt如何工作,除了MyObject不扩展Thread)

public class MyObject {
  //other variables
  private boolean isInterrupted;

  public MyObject(){
    //various setup
    isInterrupted = false;
  }
  public boolean foo() {
     while(!isInterrupted){
       //doStuff, return true or false if finished
     }

     return false;

  }
  public void setInterruptFlag(){
    isInterrupted = true;
  }

}

有了这个,我在MyThread中覆盖了中断方法:

 public void interrupt(){
   Log.d(TAG, "Interrupted!");
   if(myObject != null)
     myObject.setInterruptFlag();
   super.interrupt();
 }

这会停止函数foo并且或多或少地执行我想要的操作。但是,下次从myThread.run()调用myObject.foo()时,myThread.interrupt()会在早期被调用,整个事情就会停止。之后的下一次运行恢复正常。

查看日志输出,我只看到“电源键!”关闭屏幕时打印输出(如预期的那样)。但是,“中断!”打印输出快速连续发生4或5次,然后在用户重新启动线程时再次发生。我称之为myThread.interrupt()的唯一地方就是“电源键”!日志声明,所以我很困惑额外的电话来自哪里。系统是否会在某些地方自动调用中断,如果是,为什么?

我提到的解决方法是完全删除对myThread.interrupt的调用,而只是扩展myObject的范围,以便我可以直接从BroadcastReceiver调用myObject.setInterruptFlag()

0 个答案:

没有答案