2015-12-16 23 views
13

Voglio ritardare l'esecuzione di qualcosa, sulla falsariga di impostare un timer per il conto alla rovescia che "farà una cosa" dopo un certo periodo di tempo.Come si pianifica un'attività da eseguire una volta?

voglio il resto del mio programma per continuare a correre mentre aspetto, così ho provato a fare il mio Thread che conteneva un ritardo di un minuto:

public class Scratch { 
    private static boolean outOfTime = false; 

    public static void main(String[] args) { 
     Thread countdown = new Thread() { 
      @Override 
      public void run() { 
       try { 
        // wait a while 
        System.out.println("Starting one-minute countdown now..."); 
        Thread.sleep(60 * 1000); 

        // do the thing 
        outOfTime = true; 
        System.out.println("Out of time!"); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }; 
     countdown.start(); 

     while (!outOfTime) { 
      try { 
       Thread.sleep(1000); 
       System.out.println("do other stuff here"); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 


Anche se questo ha funzionato, più-o- meno, sembrava che ci dovrebbe essere un modo migliore per farlo.

Dopo alcune ricerche, ho trovato un mucchio di domande come queste, ma in realtà non affrontare quello che sto cercando di fare:

non ho bisogno niente di questo complica ted; Voglio solo fare una cosa sola dopo un certo periodo di tempo mentre il resto del programma è ancora in esecuzione.

Come devo fare per la pianificazione di un compito di una volta a "fare una cosa"?

risposta

16

Mentre il java.util.Timer usato per essere un buon metodo per pianificare le operazioni future, è ora preferibile utilizzare invece le classi del pacchetto java.util.concurrent.

C'è un ScheduledExecutorService progettato specificamente per eseguire un comando dopo un ritardo (o per eseguirli periodicamente, ma questo non è rilevante per questa domanda).

Ha un metodo di schedule(Runnable, long, TimeUnit) che

di creare ed eseguire un'azione di one-shot che viene attivato dopo la data di ritardo.


Utilizzando un ScheduledExecutorService si potrebbe ri-scrivere il programma come questo:

import java.util.concurrent.*; 

public class Scratch { 
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 
    public static void main(String[] args) { 
     System.out.println("Starting one-minute countdown now..."); 
     ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() { 
      @Override 
      public void run() { 
       // do the thing 
       System.out.println("Out of time!"); 
      }}, 1, TimeUnit.MINUTES); 

     while (!countdown.isDone()) { 
      try { 
       Thread.sleep(1000); 
       System.out.println("do other stuff here"); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     scheduler.shutdown(); 
    } 
} 

Una delle cose belle che si ottiene facendo le cose in questo modo è l'oggetto ScheduledFuture<?> si torna da chiamare schedule() .

Questo ti permette di sbarazzarsi del boolean variabile aggiuntiva, e basta controllare direttamente se il lavoro è stato eseguito.

È inoltre possibile annullare l'operazione pianificata se non si vuole più aspettare chiamando il suo metodo cancel().


Vedi Java Timer vs ExecutorService? per motivi per evitare di utilizzare un Timer a favore di un ExecutorService.

+0

questo esecutore pianificato verrà eseguito una volta o ogni minuto. Voglio che il mio venga eseguito solo una volta e esca. – qualebs

+0

@qualebs In questo esempio l'azione verrà eseguita una sola volta. Il tempo passato nel metodo 'schedule()' è il ritardo prima dell'esecuzione dell'azione. – azurefrog