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

Java 在Android应用程序中多次调用Thread.interrupt,但我只调用一次,java,android,multithreading,Java,Android,Multithreading,这个问题纯粹是出于好奇。我已经找到了一个解决办法,如果有人感兴趣,我会在问题的最后解释 我有一个运行后台线程的android应用程序。我想在用户按下电源键时中断此线程。为了实现这一点,我使用了如下广播接收器: public Class MyService extends Service { private MyThread myThread; //https://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-

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

我有一个运行后台线程的android应用程序。我想在用户按下电源键时中断此线程。为了实现这一点,我使用了如下广播接收器:

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
  }
}
不幸的是,仅仅中断线程是不够的,因为它没有足够频繁地轮询中断:该线程包含一个运行函数foo的对象MyObject的实例,在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的地方就是电源键的正下方!log语句,所以我不知道额外的调用来自哪里。系统是否在某些地方自动调用中断,如果是,原因是什么


我提到的解决方法是完全取消对myThread.interrupt的调用,而是扩展myObject的范围,这样我就可以直接从BroadcastReceiver调用myObject.setInterruptFlag了

不一定是问题的解决方案,但在MyObject中的isInterrupted可能应该被声明为volatile。您是100%正确的。实际上,我目前正在研究如何使用锁来让isInterrupted表现得更好,所以如果你对此有任何建议,我会向他们敞开心扉。我个人的经验是不使用中断。太多的Java类调用中断以使其对应用程序可靠。使用您自己的中断类型字段。让它变得不稳定。这样,就不会对谁、为什么、什么时候有任何疑问。查看使用Thread.stop的替代解决方案。收到。