Як запланувати періодичне завдання на Java?


183

Мені потрібно запланувати завдання, яке потрібно виконати через фіксований проміжок часу. Як я можу це зробити, підтримуючи довгі інтервали (наприклад, кожні 8 годин)?

Зараз я використовую java.util.Timer.scheduleAtFixedRate. Чи java.util.Timer.scheduleAtFixedRateпідтримує тривалі інтервали часу?

Відповіді:


260

Використовуйте ScheduledExecutorService :

 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 scheduler.scheduleAtFixedRate(yourRunnable, 8, 8, TimeUnit.HOURS);

1
Якщо ви хочете, щоб це працювало щодня у визначений час, це не чудовий спосіб зробити це, оскільки це TimeUnitстосується як і того, initialDelayі іншого period. Запуск кожні 24 години буде в кінцевому підсумку скинули , коли DST вмирає, але TimeUnitз DAYSне дозволяє вказати дрібнозернистий initialDelay. (Я думаю, внутрішня реалізація ScheduledExecutorService DAYSвсе одно перетворюється на наносекунди).
Сем Барнум

46

Слід поглянути на Quartz - це java Framework, який працює з виданнями EE та SE та дозволяє визначити завдання для виконання певного часу


23

Спробуйте таким чином ->

По-перше, створіть клас TimeTask, який виконує ваше завдання, це виглядає так:

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

то в основному класі ви створюєте завдання і запускаєте його періодично, починаючи до визначеної дати:

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

6
Щоб зробити код читабельнішим, ви можете змінити остаточний аргумент, коли ви запланували дзвінок на TimeUnit.HOURS.toMillis (8)
darrenmc

Документація для Таймера рекомендує замість цього використовувати рамку Executor.
Karan Khanna

14

Використовуйте Google Guava, AbstractScheduledServiceяк зазначено нижче:

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

}

Якщо у вас є більше подібних служб, то реєстрація всіх сервісів у ServiceManager буде хорошою, оскільки всі послуги можна запустити та зупинити разом. Прочитайте тут для отримання додаткової інформації про ServiceManager.


9

Якщо ви хочете дотримуватися java.util.Timer, ви можете використовувати його для планування на великих часових інтервалах. Ви просто проходите в період, в який ви знімаєте. Перевірте тут документацію .


5

Ці два класи можуть працювати разом для планування періодичного завдання:

Заплановане завдання

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

Виконайте розкладене завдання

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

Довідка https://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/


Найкраще рішення дотепер, більш чисте та просте у виконанні
Сальвадор Віго


4

Робіть щось щосекунди

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        //code
    }
}, 0, 1000);

1
Документація для Таймера рекомендує замість цього використовувати рамку Executor
Karan Khanna

3

Я використовую функцію Spring Framework. ( залежність від весни-контексту або мавенської залежності).

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 мій власний інтерфейс з моїм призначеним для користувача методом виконання , який я називаю мою запланованої завданням.


2

Ви спробували Spring Scheduler за допомогою приміток?

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

ви також можете це зробити з xml.

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

0

мій сервлет містить це як код, як зберегти це в планувальнику, якщо користувач натискає на це

if(bt.equals("accept")) {
    ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(1);
    String lat=request.getParameter("latlocation");
    String lng=request.getParameter("lnglocation");
    requestingclass.updatelocation(lat,lng);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.