Как установить таймер в Java?

151

Как установить таймер, скажем, на 2 минуты, чтобы попытаться подключиться к базе данных, а затем выдать исключение, если есть какие-либо проблемы в соединении?

Ankita
источник
1
Попросите ОП уточнить, хотят ли они выполнить простое действие в течение по крайней мере 2 минут, или если исключение должно быть выдано сейчас, спустя две минуты, даже если в данный момент предпринимается попытка соединения
theoshman

Ответы:

280

Итак, первая часть ответа состоит в том, как сделать то, о чем просит субъект, поскольку именно так я и интерпретировал это вначале, и несколько человек, казалось, сочли полезным. С тех пор вопрос был прояснен, и я расширил ответ на этот вопрос.

Установка таймера

Сначала вам нужно создать таймер (я использую java.utilверсию здесь):

import java.util.Timer;

..

Timer timer = new Timer();

Чтобы запустить задачу один раз, вы должны сделать:

timer.schedule(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

Чтобы повторить задание по истечении указанного вами времени:

timer.scheduleAtFixedRate(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000, 2*60*1000);

// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);

Создание тайм-аута задачи

Чтобы конкретно выполнить уточняющий вопрос, который пытается выполнить задачу в течение определенного периода времени, вы можете сделать следующее:

ExecutorService service = Executors.newSingleThreadExecutor();

try {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // Database task
        }
    };

    Future<?> f = service.submit(r);

    f.get(2, TimeUnit.MINUTES);     // attempt the task for two minutes
}
catch (final InterruptedException e) {
    // The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
    // Took too long!
}
catch (final ExecutionException e) {
    // An exception from within the Runnable task
}
finally {
    service.shutdown();
}

Обычно это выполняется с исключениями, если задача завершается в течение 2 минут. Если он длится дольше, будет генерироваться исключение TimeoutException.

Одна из проблем заключается в том, что, хотя через две минуты вы получите исключение TimeoutException, задача на самом деле продолжит выполняться , хотя, предположительно, соединение с базой данных или сетевым подключением в конечном итоге истечет и произойдет исключение в потоке. Но имейте в виду, что это может потреблять ресурсы, пока это не произойдет.

andrewmu
источник
О, я полагаю, вы неправильно поняли мою проблему, мне приходится неоднократно пытаться подключаться к базе данных до 2 минут каждый раз
Ankita
Прошу прощения, но мое требование состоит в том, что я хочу дать 2 минуты для подключения к базе данных, а затем просто выдаст сообщение об ошибке. Это похоже на то, что я хочу установить ограничение по времени, чтобы попытаться подключиться к базе данных
Ankita
7
ЧИТАТЕЛИ ОСТОРОЖНО: Этот ответ явно неверен. Он устанавливает таймер на ожидание 2 минуты, а затем запускает запрос БД после этой 2-минутной задержки, а затем он запускает его снова и снова каждые 2 минуты. Чего он НЕ делает, так это запускает запрос к БД сразу же, а затем через 2 минуты дает сбой, что, как я думаю, заданный вопрос (как пояснено в комментарии).
AgilePro
2
@AgilePro Это было правдой. Я не ответил на вопрос, поскольку он был в конечном счете заявлен, и теперь я обновил его, чтобы решить эту проблему.
Андрей
1
@ErnestasGruodis Основные API-интерфейсы перечисляют конструктор как общедоступный: docs.oracle.com/javase/7/docs/api/java/util/Timer.html#Timer () В вашем пути к классам может быть другой класс Timer - попробуйте java. util.Timer как класс.
Андрей
25

Использовать это

long startTime = System.currentTimeMillis();
long elapsedTime = 0L.

while (elapsedTime < 2*60*1000) {
    //perform db poll/check
    elapsedTime = (new Date()).getTime() - startTime;
}

//Throw your exception
nimWM
источник
1
хм ... технически это работает, за исключением того, что оно не охватывает крайние случаи, когда у вас заканчивается время, когда вы проводите опрос БД, который может потребоваться ОП
thecoshman
1
Это единственный правильный ответ. Он будет работать в одном потоке и рассчитать время окончания без дрейфа. Использование TimerTask - совершенно неправильная вещь в этом случае. Я удивлен тем, как много примеров в StackOverflow предлагают такую ​​же ошибочную вещь.
AgilePro
1
@thecoshman - реализации таймера НЕ прерывают работу БД, когда она выполняется, и не делает этого. В любом случае вы можете контролировать только время начала работы БД. Существует распространенное заблуждение, что вам нужен «таймер» для определения времени, но это не так. Вам нужно только сделать что-то, и используя текущее время, убедитесь, что вы не делаете это слишком долго.
AgilePro
допустим, вы должны либо вернуть соединение, либо бросить через ровно две минуты, это не сработает. Это произойдет, если ПОСЛЕ двух минут после попытки подключения вам все еще не удалось подключиться. В ситуации, когда проверка соединения занимает, скажем, две недели, потребуется много времени, чтобы вызвать исключение.
thecoshman
14
На самом деле это очень плохой стиль кодирования, так как цикл while постоянно запускается и проверяет вещи ... плохо для процессора и плохо для времени работы от батареи.
Бесконечно
11

Хорошо, я думаю, что теперь понимаю вашу проблему. Вы можете использовать Future, чтобы попытаться что-то сделать, и затем через некоторое время, если ничего не произошло.

Например:

FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
  @Override
  public Void call() throws Exception {
    // Do DB stuff
    return null;
  }
});

Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);

try {
  task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
  // Handle your exception
}
andrewmu
источник
Исключение выдается, но программа не завершается. Пожалуйста, помогите мне через это.
Анкита
2
Вы можете использовать класс ExecutorService вместо Executor. У него есть метод shutdown (), чтобы остановить исполнителя.
Обряды
1
Исполнители проглотят выброшенные исключения, которые вы специально не обрабатываете в Callable / Runnable. Если ваш Runnable / Callable не перехватывает и не обрабатывает само исключение, и оно предоставляется вам вместо того, чтобы вы им владеете, то вам нужно создать подкласс ScheduledExecutorService и переопределить afterExecute (обязательно вызовите super.afterExecute ()). Вторым аргументом afterExecute будет бросаемое из Runnable / Callable
Адам
3
    new java.util.Timer().schedule(new TimerTask(){
        @Override
        public void run() {
            System.out.println("Executed...");
           //your code here 
           //1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly 
        }
    },1000*5,1000*5); 
Махадев Грива
источник
просто скопируйте вредный код выше кода, он будет работать нормально. Я дал два раза «время», первый - первый раз для выполнения этого кода, а второй - для интервала времени.
Махадев Грива
Документация по Timer рекомендует вместо этого использовать среду Executor. docs.oracle.com/javase/10/docs/api/java/util/Timer.html
Каран Ханна
1

[Android], если кто-то хочет реализовать таймер на Android с помощью Java .

вам нужно использовать такой поток пользовательского интерфейса для выполнения операций.

Timer timer = new Timer();
timer.schedule(new TimerTask() {
           @Override
            public void run() {
                ActivityName.this.runOnUiThread(new Runnable(){
                    @Override
                      public void run() {
                       // do something
                      }        
                });
            }
        }, 2000));
Абхишек Гарг
источник