Пробуждение спящего потока - прерывание() против "разделения" сна на несколько снов

Это требование возникло в моем приложении для Android, но оно применимо к Java в целом. Мое приложение "делает что-то" каждые несколько секунд. Я реализовал это следующим образом (только соответствующие фрагменты - не полный код):

Snippet1:

public class PeriodicTask {

    private boolean running = true;
    private int interval = 5;

    public void startTask(){
        while (running){
            doSomething();
            try{
                Thread.sleep(interval * 1000);
            } catch(InterruptedException e){
                //Handle the exception.
            }
        }
    }

    public void stopTask(){
        this.running = false;
    }

    public void setInterval(int newInterval){
        this.interval = newInterval;
    }
}

Проблема с этим подходом, как вы можете видеть, заключается в том, что setInterval() не действует немедленно. Она вступает в силу только после завершения предыдущей функции sleep().

Поскольку мой вариант использования позволяет конечному пользователю устанавливать интервал с фиксированным шагом (в 1 секунду - от 1 до 60 секунд), я изменил реализацию, чтобы sleep выполнялся в цикле, а проверка нового значения интервала выполнялась каждую секунду следующим образом:

Snippet2:

public class PeriodicTask {

    private boolean running = true;
    private int interval = 5;
    private int loopCounter = 0;

    public void startTask(){
        while (running){
            doSomething();
            try{
                while(loopCounter < interval) {
                    Thread.sleep(1 * 1000);
                    loopCounter ++;
                }
            } catch(InterruptedException e){
                //Handle the exception.
            }
        }
    }

    public void stopTask(){
        this.running = false;
    }

    public void setInterval(int newInterval){
        synchronized (this) {
            this.interval = newInterval;
            if(newInterval < loopCounter){
                loopCounter = 0;
            }
        }
    }
}

Есть ли причина не использовать этот подход?

Недавно я наткнулся на метод interrupt() для этой цели. Но я не смог точно понять, как его использовать. Во-первых, метод interrupt, в отличие от метода sleep, не является static. Так какой Thread я прерываю?

public void setInterval(int newInterval){
        this.interval = newInterval;
        //What thread do I call interrupt() on?
    }

Во-вторых, если мне удастся прервать спящий Thread, я полагаю, что блок catch для InterruptedException будет выполнен. Однако в этот момент мне нужно будет снова вызвать startTask(). Я запутался в том, как завершить эту рекурсию. Я просмотрел несколько вопросов на SO относительно использования interrupt(), но не смог найти ничего, что помогло бы мне.

Есть какие-нибудь подсказки?


EDIT- Более подробно о точном требовании:

Мое приложение получает некоторые значения с помощью REST-вызова каждые несколько секунд. Интервал обновления настраивается пользователем.

Теперь, допустим, интервал обновления был установлен на 60 секунд. Сниппет1, который я разместил, будет работать (неправильно) следующим образом:

  • Thread goes to sleep for 60 seconds.
  • Теперь, допустим, пользователь меняет интервал обновления на 5 секунд. Поток все еще спит.
  • Задача PeriodicTask увидит новый интервал обновления только после истечения 60 секунд.

Точное требование заключается в том, что новые интервалы обновления должны вступать в силу немедленно (или, по крайней мере, не позднее, чем через 1 секунду после установки - так как это то, что пользователь, скорее всего, воспримет в любом случае).

Мои Сниппет2 и Сниппет3 являются попытками достичь этого требования.

5
задан curioustechizen 4 January 2012 в 06:37
поделиться