Я делаю некий таймер. При его запуске выполняется какая-то последовательность действий, после чего поток должен закрыться и не грузить дальнейшую работу программы. Как мне его адекватно остановиться, я что-то не могу сообразить. Тренировался останавливать поток на данном примере. Грубо говоря перезапускать его у меня получается, а вот с полным его прерыванием возникают проблемы, как это можно решить? Еще есть такой вопрос, возможно ли в методе repeatTimer
не завершать и создавать поток, а просто перезапускать (заставить отсчитать эти 5 секунд заново)? Просто в моей реализации это выглядит слишком топорно.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Solution {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
for (int i = 1; i <= 15; i += 1) {
System.out.println(i);
if (i == 3) {
timer.schedule(new RunTimer(), 5, TimeUnit.SECONDS);
}
if (i == 7) {
timer = repeatTimer(timer);
}
Thread.sleep(1000);
}
}
public static void dropTimer (ScheduledExecutorService timer) {
timer.shutdownNow();
}
public static ScheduledExecutorService repeatTimer (ScheduledExecutorService timer) {
dropTimer(timer);
return startTimer();
}
public static ScheduledExecutorService startTimer () {
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.schedule(new RunTimer(), 5, TimeUnit.SECONDS);
return timer;
}
static class RunTimer implements Runnable {
@Override
public void run() {
System.out.println("TIMER");
}
}
}
Там есть метод scheduleAtFixedRate
, которsый позволяет исполнять задачу с интервалом, а не один раз.
Первый способ - тут возможны гонки, если runnable
выполняется очень быстро, маленький интервал и малое число повторений, то Ява может не успеть проставить ссылку в self
public static void execute(ScheduledExecutorService executor, final Runnable runnable, int times, long interval, TimeUnit timeUnit) {
final AtomicInteger counter = new AtomicInteger(times);
final AtomicReference<ScheduledFuture> self = new AtomicReference<>();
final Runnable wrapper = new Runnable() {
try {
runnable.run();
} finally {
if (counter.decrementAndGet() == 0) {
self.get().cancel();
}
}
};
self.set(executor.scheduleAtFixedRate(wrapper, interval, interval, timeUnit));
// return self.get(); // Опционально можно получить доступ к задаче и управлять её жизненным циклом
}
Второй способ - гонок нет, но и в отличие от первого, нельзя наружу вернуть ScheduledFuture и получить дополнительный контроль на жизнью задачи.
public static void execute(final ScheduledExecutorService executor, final Runnable runnable, final int times, long interval, TimeUnit timeUnit) {
final Runnable wrapper = new Runnable() {
try {
runnable.run();
} finally {
if (times > 1) {
execute(executor, runnable, times-1, interval, timeUnit);
}
}
};
executor.schedule(wrapper, interval, timeUnit));
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Несколько раз встречал в таблицах базы, относящейся к веб-приложению на Java, столбцы, играющие роль флага, но имеющие не привычный тип bool, а smallint...
Похоже ошибка в неправильном использовании if (actionequals("back")){continue;}