Это требование появилось в моем приложении для 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 () не сразу эффективен. Действует только после завершения предыдущего сна ().
Поскольку мой вариант использования позволяет конечному пользователю устанавливать интервал фиксированными шагами (от 1 секунды - от 1 до 60 секунд), я изменил реализацию так, чтобы она спала в цикле; и проверяйте новое значение интервала каждую секунду следующим образом:
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()
для этой цели. Но я не мог точно понять, как его использовать. С одной стороны, метод прерывания, в отличие от метода сна, не равен 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 секунд. Snippet1, который я разместил, будет работать (неправильно) следующим образом:
- Поток засыпает на 60 секунд.
- Теперь допустим, пользователь изменяет интервал обновления до 5 секунд. Нить все еще спит.
-
PeriodicTask
будет видеть новый интервал обновления только после истечения 60 секунд.
Точное требование заключается в том, что новые интервалы обновления должны вступать в силу немедленно (или, по крайней мере, не позднее, чем через 1 секунду после установки - поскольку это то, что пользователь, вероятно, все равно будет воспринимать).
Мои Snippet2 и Snippet3 являются попытками выполнить это требование.