¿Cómo programar una tarea periódica en Java?

183

Necesito programar una tarea para que se ejecute en un intervalo de tiempo fijo. ¿Cómo puedo hacer esto con soporte de intervalos largos (por ejemplo, cada 8 horas)?

Actualmente estoy usando java.util.Timer.scheduleAtFixedRate. ¿ java.util.Timer.scheduleAtFixedRateSoporta largos intervalos de tiempo?

RYN
fuente

Respuestas:

261

Utilice un servicio de servicio programado :

 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 scheduler.scheduleAtFixedRate(yourRunnable, 8, 8, TimeUnit.HOURS);
b_erb
fuente
1
Si desea que esto se ejecute todos los días a una hora específica, no hay una excelente manera de hacerlo, porque se TimeUnitaplica tanto a la initialDelaycomo a la period. La ejecución cada 24 horas terminará siendo interrumpida cuando se active el horario de verano, pero una TimeUnitde DAYSno le permite especificar un grano fino initialDelay. (Creo que la implementación interna ScheduledExecutorService se convierte DAYSa nanosegundos de todos modos).
Sam Barnum
46

Debería echar un vistazo a Quartz , es un framework java que funciona con las ediciones EE y SE y permite definir trabajos para ejecutar un tiempo específico

Jorge
fuente
23

Intenta de esta manera ->

En primer lugar, cree una clase TimeTask que ejecute su tarea, se ve así:

public class CustomTask extends TimerTask  {

   public CustomTask(){

     //Constructor

   }

   public void run() {
       try {

         // Your task process

       } catch (Exception ex) {
           System.out.println("error running thread " + ex.getMessage());
       }
    }
}

luego, en la clase principal, crea una instancia de la tarea y la ejecuta periódicamente iniciada en una fecha específica:

 public void runTask() {

        Calendar calendar = Calendar.getInstance();
        calendar.set(
           Calendar.DAY_OF_WEEK,
           Calendar.MONDAY
        );
        calendar.set(Calendar.HOUR_OF_DAY, 15);
        calendar.set(Calendar.MINUTE, 40);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);



        Timer time = new Timer(); // Instantiate Timer Object

        // Start running the task on Monday at 15:40:00, period is set to 8 hours
        // if you want to run the task immediately, set the 2nd parameter to 0
        time.schedule(new CustomTask(), calendar.getTime(), TimeUnit.HOURS.toMillis(8));
}
Shessuky
fuente
66
Para que el código sea más legible, puede cambiar el argumento final en su llamada programada a TimeUnit.HOURS.toMillis (8)
darrenmc
La documentación para Timer recomienda usar el marco Ejecutor en su lugar.
Karan Khanna
14

Use Google Guava AbstractScheduledServicecomo se indica a continuación:

public class ScheduledExecutor extends AbstractScheduledService
{
   @Override
   protected void runOneIteration() throws Exception
   {
      System.out.println("Executing....");
   }

   @Override
   protected Scheduler scheduler()
   {
        return Scheduler.newFixedRateSchedule(0, 3, TimeUnit.SECONDS);
   }

   @Override
   protected void startUp()
   {
       System.out.println("StartUp Activity....");
   }


   @Override
   protected void shutDown()
   {
       System.out.println("Shutdown Activity...");
   }

   public static void main(String[] args) throws InterruptedException
   {
       ScheduledExecutor se = new ScheduledExecutor();
       se.startAsync();
       Thread.sleep(15000);
       se.stopAsync();
   }

}

Si tiene más servicios como este, entonces registrar todos los servicios en ServiceManager será bueno ya que todos los servicios se pueden iniciar y detener juntos. Lea aquí para más información sobre ServiceManager.

Aride Chettali
fuente
9

Si desea seguir java.util.Timer, puede usarlo para programar a intervalos de tiempo grandes. Simplemente pasa en el período que está disparando. Consulte la documentación aquí .

Belizzle
fuente
5

Estas dos clases pueden trabajar juntas para programar una tarea periódica:

Tarea programada

import java.util.TimerTask;
import java.util.Date;

// Create a class extending TimerTask
public class ScheduledTask extends TimerTask {
    Date now; 
    public void run() {
        // Write code here that you want to execute periodically.
        now = new Date();                      // initialize date
        System.out.println("Time is :" + now); // Display current time
    }
}

Ejecutar tarea programada

import java.util.Timer;

public class SchedulerMain {
    public static void main(String args[]) throws InterruptedException {
        Timer time = new Timer();               // Instantiate Timer Object
        ScheduledTask st = new ScheduledTask(); // Instantiate SheduledTask class
        time.schedule(st, 0, 1000);             // Create task repeating every 1 sec
        //for demo only.
        for (int i = 0; i <= 5; i++) {
            System.out.println("Execution in Main Thread...." + i);
            Thread.sleep(2000);
            if (i == 5) {
                System.out.println("Application Terminates");
                System.exit(0);
            }
        }
    }
}

Referencia https://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/

SumiSujith
fuente
La mejor solución hasta ahora, más limpia y fácil de implementar
Salvador Vigo
4

Si su aplicación ya está utilizando Spring Framework, tiene la programación integrada

Negro
fuente
4

Haz algo cada segundo

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        //code
    }
}, 0, 1000);
Duchic
fuente
1
La documentación para Timer recomienda usar el marco Ejecutor en su lugar
Karan Khanna el
3

Yo uso la función de Spring Framework. ( dependencia de jar de contexto de primavera o maven).

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


@Component
public class ScheduledTaskRunner {

    @Autowired
    @Qualifier("TempFilesCleanerExecution")
    private ScheduledTask tempDataCleanerExecution;

    @Scheduled(fixedDelay = TempFilesCleanerExecution.INTERVAL_TO_RUN_TMP_CLEAN_MS /* 1000 */)
    public void performCleanTempData() {
        tempDataCleanerExecution.execute();
    }

}

ScheduledTask es mi propia interfaz con mi método personalizado ejecutar , que llamo como mi tarea programada.

Yan Khonski
fuente
2

¿Has probado Spring Scheduler con anotaciones?

@Scheduled(cron = "0 0 0/8 ? * * *")
public void scheduledMethodNoReturnValue(){
    //body can be another method call which returns some value.
}

puedes hacer esto con xml también.

 <task:scheduled-tasks>
   <task:scheduled ref = "reference" method = "methodName" cron = "<cron expression here> -or- ${<cron expression from property files>}"
 <task:scheduled-tasks>
madhu_karnati
fuente
0

mi servlet contiene esto como un código de cómo mantener esto en el planificador si un usuario presiona aceptar

if(bt.equals("accept")) {
    ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(1);
    String lat=request.getParameter("latlocation");
    String lng=request.getParameter("lnglocation");
    requestingclass.updatelocation(lat,lng);
}
Gopal Krishna Mareti
fuente