Завершить поток, похоже, не работает

У меня есть следующий поток в моем классе обслуживания.

public class MyLocalThread extends Thread {
  @Override
  public void run() {
    while (!Thread.interrupted()) {
      try {
        //do some work
         Thread.sleep(4000);
      } catch (Exception e){
          System.out.println("Exception occur" + e.getMessage());
          e.printStackTrace();
      }
    }
  }
}

Я пытаюсь запустить и остановить поток, когда получаю действие Intent от MainActivity.java. Я установил BroadcastReceiver для связи между сервисом и активностью. Я начинаю тему следующим образом. Поток начинается нормально, и я получаю тост.

public class MyReceiver extends BroadcastReceiver {

    MyLocalThread thread = new MyLocalThread();

  @Override
  public void onReceive(Context context, Intent intent) {

    String action = intent.getAction();

    if (action.equals("com.example.START")) {

      //starts the thread

      thread.start();

      Toast.makeText(context, "Service is started.", Toast.LENGTH_LONG).show();

    } else if (action.equals("com.example.STOP")) {

      //stops the thread
    thread.interrupt();
      Toast.makeText(context, "Service has stopped.", Toast.LENGTH_LONG).show();

    }
  }
}

Но при попытке остановить мой тред т.е.second action не работает. Я получаю сообщение TOAST о том, что служба остановлена, но мой поток продолжает работать. Это не прекращается. Я не знаю, что я делаю неправильно?

Что делает runnable в цикле while? Может быть, он спит или заблокирован, ожидая ввода?

Juan 12.07.2019 16:56

Я предполагаю, что у вас опечатка - метод запуска должен быть while (!Thread.interrupted). Также обратите внимание, что при использовании статического метода (в отличие от метода экземпляра isInterrupted) статус прерывания очищается при каждом вызове. (Не очищается на isInterrupted).

user2711811 12.07.2019 18:48

У вас также есть состояние гонки: start не обязательно происходит немедленно - это зависит от планировщика - поэтому теоретически вы можете пытаться остановить поток (прерывание) еще до его запуска и, таким образом, пропустить прерывание (поскольку оно не было запущено). т началось).

user2711811 12.07.2019 18:56
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
125
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Обновлено:

Вы можете вызвать thread.interrupt(), чтобы прервать поток и поставить Thread.interrupted() проверку вместо создания логического значения.

class MyLocalThread extends Thread { 
    public void run() { 
      if (!Thread.interrupted()) {
        try {
        //do some work
       }
        catch (InterruptedException e) { 
            System.out.println("InterruptedException occur"); 
        } 
      }
    } 
}  

Прервать поток следующим образом:

MyLocalThread thread = new MyLocalThread(); 
        thread.start(); 
  // when need to stop the thread
        thread.interrupt(); 

Это ничего не меняет - если бы run был ложным, он вышел бы из цикла while, достиг бы нижней части функции и автоматически вернулся.

Gabe Sechan 12.07.2019 16:51

Декс, спасибо за ваши усилия, я проверю это и вернусь к вам через минуту.

cantona_7 12.07.2019 16:52

@cantona_7 cantona_7 Я обновил ответ. Это должно сработать. Но чтобы вы знали, мы ничего не можем сделать, чтобы остановить поток. мы можем только уведомить систему, чтобы прервать его.

Deˣ 12.07.2019 17:27

Я только что обновил вопрос, если вы посмотрите, вы увидите мою реализацию.

cantona_7 12.07.2019 17:31

На самом деле я это уже видел. и мой подход был основан на этом посте. Кажется, я где-то пропустил сюжет.

cantona_7 12.07.2019 17:35

Эта функциональность встроена в Thread. Посмотрите на thread.interrupt и thread.isInterrupted. Нет причин переписывать эту функциональность.

привет, но я не использую прерывание (), верно? Я пытаюсь прекратить. Извините, если это глупый вопрос.

cantona_7 12.07.2019 16:55

Interrupt() устанавливает флаг. isInterrupted() проверяет флаг. Это избавляет от необходимости использовать ваш рабочий флаг, и он будет реализован правильно.

Gabe Sechan 12.07.2019 16:56

Использование прерывания имеет то преимущество, что если поток ожидает, он будет разбужен InterruptedException, где вы можете предпринять действия, чтобы красиво завершить поток.

Juan 12.07.2019 17:02

Что бы вы предложили мне сделать? Использовать прерывание() вместо завершения?

cantona_7 12.07.2019 17:15

Другие вопросы по теме