Пробуждение спящего потока - прерывание () против «разделения» сна на несколько снов
Это требование появилось в моем приложении для 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 являются попытками выполнить это требование.