Wie plane ich eine periodische Aufgabe in Java?

183

Ich muss eine Aufgabe planen, die in einem festgelegten Zeitintervall ausgeführt werden soll. Wie kann ich dies mit Unterstützung langer Intervalle tun (zum Beispiel alle 8 Stunden)?

Ich benutze gerade java.util.Timer.scheduleAtFixedRate. Hat java.util.Timer.scheduleAtFixedRatelange Zeitintervalle unterstützt?

RYN
quelle

Antworten:

260

Verwenden Sie einen ScheduledExecutorService :

 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 scheduler.scheduleAtFixedRate(yourRunnable, 8, 8, TimeUnit.HOURS);
b_erb
quelle
1
Wenn Sie möchten, dass dies jeden Tag zu einer bestimmten Zeit ausgeführt wird, gibt es keine gute Möglichkeit, dies zu tun, da dies TimeUnitsowohl für das initialDelayals auch für das gilt period. Wenn Sie alle 24 Stunden laufen, wird die Sommerzeit unterbrochen, wenn Sie die Sommerzeit aktivieren. Mit einem TimeUnitvon können Sie DAYSjedoch keine Feinkörnigkeit angeben initialDelay. (Ich denke, die interne ScheduledExecutorService-Implementierung wird DAYSsowieso in Nanosekunden konvertiert ).
Sam Barnum
46

Sie sollten sich Quartz ansehen, ein Java-Framework, das mit EE- und SE-Editionen funktioniert und es ermöglicht, Jobs für die Ausführung einer bestimmten Zeit zu definieren

Jorge
quelle
23

Versuchen Sie es auf diese Weise ->

Erstellen Sie zunächst eine Klasse TimeTask, die Ihre Aufgabe ausführt. Sie sieht folgendermaßen aus:

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

Dann instanziieren Sie in der Hauptklasse die Aufgabe und führen sie regelmäßig ab einem bestimmten Datum aus:

 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
quelle
6
Um den Code besser lesbar zu machen, können Sie das letzte Argument in Ihrem geplanten Aufruf von TimeUnit.HOURS.toMillis (8)
ändern
In der Dokumentation zu Timer wird empfohlen, stattdessen das Executor-Framework zu verwenden.
Karan Khanna
14

Verwenden Sie Google Guava AbstractScheduledServicewie folgt :

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

}}

Wenn Sie über mehr Dienste wie diesen verfügen, ist die Registrierung aller Dienste in ServiceManager sinnvoll, da alle Dienste zusammen gestartet und gestoppt werden können. Lesen Sie hier mehr über ServiceManager.

Aride Chettali
quelle
9

Wenn Sie dabei bleiben möchten java.util.Timer, können Sie damit in großen Zeitintervallen planen. Sie vergehen einfach in der Zeit, für die Sie fotografieren. Überprüfen Sie die Dokumentation hier .

Belizzle
quelle
5

Diese beiden Klassen können zusammenarbeiten, um eine periodische Aufgabe zu planen:

Geplante Aufgabe

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

Geplante Aufgabe ausführen

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

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

SumiSujith
quelle
Beste Lösung bis jetzt, sauberer und einfacher zu implementieren
Salvador Vigo
4

Wenn Ihre Anwendung bereits das Spring Framework verwendet, ist die Zeitplanung integriert

Schwarz
quelle
4

Mach jede Sekunde etwas

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        //code
    }
}, 0, 1000);
Herzogtum
quelle
1
In der Dokumentation für Timer wird empfohlen, stattdessen das Executor-Framework zu verwenden
Karan Khanna,
3

Ich benutze die Funktion von Spring Framework. ( Spring-Context- Jar- oder Maven-Abhängigkeit).

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 ist meine eigene Schnittstelle mit meiner benutzerdefinierten Methode execute , die ich als geplante Aufgabe aufrufe.

Yan Khonski
quelle
2

Haben Sie Spring Scheduler mit Anmerkungen ausprobiert ?

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

Sie können dies auch mit XML tun.

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

Mein Servlet enthält dies als Code, wie dies im Scheduler beibehalten wird, wenn ein Benutzer auf "Akzeptieren" drückt

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
quelle