2010-10-28 40 views
114

Come impostare un timer, ad esempio per 2 minuti, per provare a connettersi a un database quindi generare un'eccezione se c'è qualche problema nella connessione?Come impostare un timer in Java?

+1

Coul l'OP chiarire se desiderano semplicemente tentare l'azione per almeno 2 minuti, o se l'eccezione deve essere lanciata ora più tardi i due minuti, anche se è attualmente in corso un tentativo di connessione – thecoshman

risposta

224

Quindi la prima parte della risposta è come fare ciò che il soggetto chiede in quanto è stato il modo in cui l'ho inizialmente interpretato e alcune persone sembrano trovare utili. La domanda è stata chiarita da allora e ho esteso la risposta per risolverlo.

L'impostazione di un timer

Per prima cosa è necessario creare un timer (sto usando la versione java.util qui):

import java.util.Timer; 

..

Timer timer = new Timer(); 

Per eseguire il compito una volta fatto:

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

Per avere la ripetizione compito dopo la durata si dovrebbe fare:

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

Fare un timeout compito

Per fare precisamente ciò che la domanda chiarito chiede, che sta tentando di eseguire un compito per un determinato periodo di tempo, si potrebbe procedere come segue:

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

Questo eseguirà normalmente con le eccezioni se l'attività viene completata entro 2 minuti . Se viene eseguito più a lungo, verrà lanciata la TimeoutException.

Un problema è che, anche se si otterrà un TimeoutException dopo i due minuti, il compito sarà in realtà continuerà a funzionare, anche se presumibilmente un database o connessione di rete alla fine timeout e un'eccezione nel thread. Ma sappi che potrebbe consumare risorse finché ciò non accadrà.

+0

Oh immagino che tu abbia il mio problema sbagliato, devo provare ripetutamente a connettermi al database fino a 2 minuti ogni volta – Ankita

+1

Ho aggiornato la mia risposta alla copertina ripetendo ogni 2 minuti – andrewmu

+0

Mi dispiace ma il mio requisito è che voglio dare 2 minuti per connettermi al database e poi getterò solo un messaggio di errore. È come se volessi impostare un limite di tempo per provare a connettermi al database – Ankita

9

Ok, penso di capire il tuo problema ora. Puoi usare un futuro per provare a fare qualcosa e poi sospendere dopo un po 'se non è successo nulla.

Es .:

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 
} 
+0

Viene generata un'eccezione ma il programma non viene terminato.Per favore aiutatemi attraverso questo. – Ankita

+2

Potete usare invece la classe ExecutorService dell'Executor .Esso il metodo shutdown() per arrestare l'executor. – Rites

+1

Executors ingerirà eccezioni generate che non si gestiscono specificamente in Callable/Runnable.Se il Runnable/Callable non cattura e gestisce l'eccezione stessa ed è fornito a te e tu lo possiedi, quindi devi eseguire la sottoclasse di ScheduledExecutorService e sovrascrivere afterExecute (assicurati di chiamare super.afterExecute()). Il secondo argomento di afterExecute sarà il throwable da Runnable/Callable – adam

6

Come fermare il timer?Stop e giocare di nuovo quando fare qualcosa in questo codice

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

Quando uso il timer.cancel();

si fermerà, ma se vicino la forma e aprire di nuovo l'eccezione viene lanciata

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Timer already cancelled. 
    at java.util.Timer.sched(Timer.java:354) 
    at java.util.Timer.scheduleAtFixedRate(Timer.java:296) 
    at View.Electronic_Meeting.this_componentShown(Electronic_Meeting.java:295) 
    at View.Electronic_Meeting.access$000(Electronic_Meeting.java:36) 
    at View.Electronic_Meeting$1.componentShown(Electronic_Meeting.java:85) 
    at java.awt.AWTEventMulticaster.componentShown(AWTEventMulticaster.java:162) 
    at java.awt.Component.processComponentEvent(Component.java:6095) 
    at java.awt.Component.processEvent(Component.java:6043) 
    at java.awt.Container.processEvent(Container.java:2041) 
    at java.awt.Component.dispatchEventImpl(Component.java:4630) 
    at java.awt.Container.dispatchEventImpl(Container.java:2099) 
    at java.awt.Component.dispatchEvent(Component.java:4460) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) 
17

Usa questo

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

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

//Throw your exception 
+1

hmm ... questo funzionerebbe tecnicamente, tranne che non copre i casi limite, dove il tempo si esaurisce quando si sta eseguendo un sondaggio DB, w che può essere richiesto dall'OP – thecoshman

+0

Questa è l'unica risposta corretta. Verrà eseguito su un singolo thread e calcolerà l'ora di fine senza deriva. L'utilizzo di un TimerTask è esattamente la cosa sbagliata da fare in questo caso. Sono sorpreso di quanti esempi su StackOverflow suggeriscano questo stesso tipo di cosa sbagliata. – AgilePro

+1

@thecoshman - le implementazioni del timer NON interrompono l'operazione DB una volta che è in corso, né ciò. In ogni caso, è possibile controllare solo l'ora in cui si avvia l'operazione DB. C'è un malinteso comune sul fatto che sia necessario un "timer" per temporizzare le cose, ma non è così. Devi solo fare qualcosa e, usando l'ora corrente, assicurati di non farlo troppo a lungo. – AgilePro

1
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); 
+0

copia solo il codice sopra il codice funzionerà correttamente. Ho dato due volte 'tempo' per primo è per la prima volta per eseguire questo codice e il secondo è per il tempo di intervallo. –

Problemi correlati