¿Cómo establecer un temporizador en Java?

¿Cómo establecer un temporizador, por ejemplo de 2 minutos, para intentar conectarse a una base de datos y luego lanzar una excepción si hay algún problema en la conexión?

Solución

Así que la primera parte de la respuesta es cómo hacer lo que pide el tema, ya que así fue como lo interpreté inicialmente y a algunas personas les pareció útil. La pregunta se aclaró desde entonces y he ampliado la respuesta para abordar eso.

Configuración de un temporizador

Primero tienes que crear un Timer (aquí estoy usando la versión java.util):

import java.util.Timer;

..

Timer timer = new Timer();

Para ejecutar la tarea una vez se haría:

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);

Para que la tarea se repita después de la duración harías:

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);

Hacer que una tarea se repita después de su duración

Para hacer específicamente lo que pide la pregunta aclarada, es decir, intentar realizar una tarea durante un periodo de tiempo determinado, se podría hacer lo siguiente:

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();
}

Esto se ejecutará normalmente con excepciones si la tarea se completa en 2 minutos. Si se ejecuta más tiempo, se lanzará la TimeoutException.

Un problema es que aunque se obtenga una TimeoutException después de los dos minutos, la tarea continuará ejecutándose, aunque presumiblemente una base de datos o una conexión de red eventualmente se agotará y lanzará una excepción en el hilo. Pero ten en cuenta que podría consumir recursos hasta que eso ocurra.

Comentarios (9)

Utiliza esto

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

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

//Throw your exception
Comentarios (10)

Vale, creo que ahora entiendo tu problema. Puedes usar un Futuro para intentar hacer algo y luego hacer un timeout después de un rato si no ha pasado nada.

Por ejemplo

FutureTask task = new FutureTask(new Callable() {
  @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
}
Comentarios (3)