2016-12-27 124 views
0

我有這兩種創建和停止線程的方法。然而,即使在第一個方法被調用之後,線程仍然保持運行。 (我創建了一個類的對象,並從另一個類中調用它們)。不能停止線程

private Thread thread; 

public void stopAlarm() { 
    Log.i(LOG_TAG, "stopAlarm called"); 
    sendAlarm = false; 
    if (!thread.equals(null)) { 
     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 


public void triggerAlarm() { 
    Runnable alarmTest = new Runnable() { 
     @Override 
     public void run() { 
      while (sendAlarm) { 
       Log.i(LOG_TAG, String.valueOf(sendAlarm)); 
      } 
     } 
    }; 
    thread = new Thread(Test); 
    thread.start(); 
} 

當stopAlarm被稱爲線程總是空,雖然triggerAlarm被稱爲(線程運行)後,它被調用。

+1

make'sendAlarm'' volatile' –

+2

首先,你從來沒有寫過類似thread.equals(null)的東西,因爲如果它相等,你會得到一個異常,而不是使用線程== null秒你能否請發佈更多你的代碼讓你的問題更加難以理解 – urag

+0

沒有幫助,它仍然是真的,即使在調用stopAlarm() – user3742929

回答

1

您的問題是由線程範圍引起的。線程作用域是在作用域中創建具有相同變量的線程時創建的,但不能從外部世界中更改這些變量。在Android中管理runnables的最佳做法是使用Handler

Handler handler = new Handler(); 
Runnable alarmTest = new Runnable() { 
    @Override 
    public void run() { 
     Log.i(LOG_TAG, String.valueOf(sendAlarm)); 
     handler.post(alarmTest, 5000); //wait 5 sec and run again 
     //you can stop from outside 
    } 
}; 

之後的定義,以啓動運行的:

handler.post(alarmTest,0); //wait 0 ms and run 

,以停止運行的:

handler.removeCallbacks(alarmTest); 

編輯:等待語句,循環

編輯:完整的解決方案

Handler handler = new Handler(); 
Runnable alarmTest = new Runnable() { 
    @Override 
    public void run() { 
     Log.i(LOG_TAG, String.valueOf(sendAlarm)); 
     handler.post(alarmTest, 5000); //wait 5 sec and run again 
     //you can stop from outside 
    } 
}; 

public void stopAlarm() { 
    Log.i(LOG_TAG, "stopAlarm called"); 
    handler.removeCallbacks(alarmTest); 
} 


public void triggerAlarm() { 
    handler.post(alarmTest,0); //wait 0 ms and run 
} 
+0

工程,但完全凍結我的gui,使stopAlarm()無用。 – user3742929

+1

檢查您是否發佈了很多alarmTest,可能會有多個實例 – cokceken

+0

包含handler.post(alarmTest)的方法僅調用一次。 – user3742929

1

根據您的操作系統,您可能會發現使您的線程volatile可能會解決此問題。

private volatile Thread thread; 

但是 - 有更好的方法來做到這一點。一個非常有用的方法是使用一個小的(只有一個入口)BlockingQueue這是由正在運行的線程編輯的poll

// Use a BlockingQueue to signal the alarm to stop. 
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1); 

public void stopAlarm() { 
    stop.add("Stop"); 
} 


public void triggerAlarm() { 
    new Thread(() -> { 
     try { 
      while (stop.poll(1, TimeUnit.SECONDS) == null) { 
       // Stuff 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    }).start(); 
} 

很顯然,你將有管理的邊緣情況下,像沒有報警運行時,如果有人呼叫stopAlarm