Это требование возникло в моем приложении для 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(), но не смог найти ничего, что помогло бы мне.
Есть какие-нибудь подсказки?
Мое приложение получает некоторые значения с помощью REST-вызова каждые несколько секунд. Интервал обновления настраивается пользователем.
Теперь, допустим, интервал обновления был установлен на 60 секунд. Сниппет1, который я разместил, будет работать (неправильно) следующим образом:
PeriodicTask
увидит новый интервал обновления только после истечения 60 секунд. Точное требование заключается в том, что новые интервалы обновления должны вступать в силу немедленно (или, по крайней мере, не позднее, чем через 1 секунду после установки - так как это то, что пользователь, скорее всего, воспримет в любом случае).
Мои Сниппет2 и Сниппет3 являются попытками достичь этого требования.