শিডিউডএক্সেকিউটারস সার্ভিস ব্যবহার করে নির্দিষ্ট সময়ে প্রতিদিন নির্দিষ্ট কাজ কীভাবে চালানো যায়?


90

আমি প্রতিদিন সকাল at টায় একটি নির্দিষ্ট কাজ চালানোর চেষ্টা করছি। সুতরাং আমি এটির জন্য ব্যবহারের সিদ্ধান্ত নিয়েছি ScheduledExecutorServiceতবে এখন পর্যন্ত আমি উদাহরণগুলি দেখেছি যা প্রতি কয়েক মিনিটের মধ্যে কীভাবে টাস্ক চালানো যায় তা দেখায়।

এবং আমি এমন কোনও উদাহরণ খুঁজে পাচ্ছি না যা দেখায় যে কীভাবে প্রতিদিন একটি নির্দিষ্ট সময় সকালে (সকাল 5 টা) সকালে কোনও কাজ চালানো যায় এবং পাশাপাশি দিবালোকের সময় সাশ্রয়ের সময়কে বিবেচনা করে -

নীচে আমার কোড যা প্রতি 15 মিনিটে চলবে -

public class ScheduledTaskExample {
    private final ScheduledExecutorService scheduler = Executors
        .newScheduledThreadPool(1);

    public void startScheduleTask() {
    /**
    * not using the taskHandle returned here, but it can be used to cancel
    * the task, or check if it's done (for recurring tasks, that's not
    * going to be very useful)
    */
    final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(
        new Runnable() {
            public void run() {
                try {
                    getDataFromDatabase();
                }catch(Exception ex) {
                    ex.printStackTrace(); //or loggger would be better
                }
            }
        }, 0, 15, TimeUnit.MINUTES);
    }

    private void getDataFromDatabase() {
        System.out.println("getting data...");
    }

    public static void main(String[] args) {
        ScheduledTaskExample ste = new ScheduledTaskExample();
        ste.startScheduleTask();
    }
}

কোনও উপায় আছে কি না, আমি ScheduledExecutorServiceদিবালোকের সময় সাশ্রয় করার সময়কেও বিবেচনা করে প্রতিদিন সকাল 5 টা থেকে প্রতিদিন চালানোর জন্য একটি সময় নির্ধারণ করতে পারি ?

এবং এছাড়াও এই TimerTaskজন্য ভাল বা ScheduledExecutorService?


পরিবর্তে কোয়ার্টজ জাতীয় কিছু ব্যবহার করুন।
মিলিমুজ

উত্তর:


113

বর্তমান জাভা এসই 8 রিলিজের সাথে এটির দুর্দান্ত তারিখের সময় এপিআই সহ java.timeএই জাতীয় গণনা java.util.Calendarএবং ব্যবহারের পরিবর্তে আরও সহজেই করা যায় java.util.Date

আপনার ব্যবহারের ক্ষেত্রে কোনও কাজের সময় নির্ধারণের উদাহরণ হিসাবে এখন:

ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));
ZonedDateTime nextRun = now.withHour(5).withMinute(0).withSecond(0);
if(now.compareTo(nextRun) > 0)
    nextRun = nextRun.plusDays(1);

Duration duration = Duration.between(now, nextRun);
long initalDelay = duration.getSeconds();

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);            
scheduler.scheduleAtFixedRate(new MyRunnableTask(),
    initalDelay,
    TimeUnit.DAYS.toSeconds(1),
    TimeUnit.SECONDS);

initalDelayমধ্যে সঞ্চালনের বিলম্ব নির্ধারণকারী জিজ্ঞাসা করতে নির্ণয় করা হয় TimeUnit.SECONDS। ইউনিট মিলিসেকেন্ড এবং নীচে সময় পার্থক্য সম্পর্কিত বিষয়গুলি এই ব্যবহারের ক্ষেত্রে তুচ্ছ বলে মনে হচ্ছে। তবে আপনি এখনও মিলিসেকেন্ডে শিডিয়ুলিং গণনাগুলি ব্যবহার করতে duration.toMillis()এবং TimeUnit.MILLISECONDSপরিচালনা করতে পারেন ।

এবং এছাড়াও টাইমারটাস্ক এই বা সময়সূচী এক্সেকিউটারসেবার জন্য আরও ভাল?

না: ScheduledExecutorService আপাতদৃষ্টিতে এর চেয়ে ভাল TimerTaskস্ট্যাকওভারফ্লো ইতিমধ্যে আপনার জন্য একটি উত্তর আছে

@ প্যাডিডি থেকে,

আপনার কাছে এখনও সমস্যা রয়েছে যার দ্বারা আপনার যদি সঠিক স্থানীয় সময়টি চালানো চান তবে আপনাকে বছরে দুবার এটি পুনরায় চালু করতে হবে। সময়সূচিএটিফিক্সডরেট এটি কাটবে না যতক্ষণ না আপনি সারা বছর একই ইউটিসি সময় নিয়ে খুশি হন।

যেহেতু এটি সত্য এবং @ প্যাডিডি ইতিমধ্যে একটি workaround দিয়েছে (তাকে +1), তাই আমি জাভা 8 তারিখের সময় এপিআই সহ একটি কাজের উদাহরণ সরবরাহ করছি ScheduledExecutorServiceডেমন থ্রেড ব্যবহার করা বিপজ্জনক

class MyTaskExecutor
{
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
    MyTask myTask;
    volatile boolean isStopIssued;

    public MyTaskExecutor(MyTask myTask$) 
    {
        myTask = myTask$;

    }

    public void startExecutionAt(int targetHour, int targetMin, int targetSec)
    {
        Runnable taskWrapper = new Runnable(){

            @Override
            public void run() 
            {
                myTask.execute();
                startExecutionAt(targetHour, targetMin, targetSec);
            }

        };
        long delay = computeNextDelay(targetHour, targetMin, targetSec);
        executorService.schedule(taskWrapper, delay, TimeUnit.SECONDS);
    }

    private long computeNextDelay(int targetHour, int targetMin, int targetSec) 
    {
        LocalDateTime localNow = LocalDateTime.now();
        ZoneId currentZone = ZoneId.systemDefault();
        ZonedDateTime zonedNow = ZonedDateTime.of(localNow, currentZone);
        ZonedDateTime zonedNextTarget = zonedNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec);
        if(zonedNow.compareTo(zonedNextTarget) > 0)
            zonedNextTarget = zonedNextTarget.plusDays(1);

        Duration duration = Duration.between(zonedNow, zonedNextTarget);
        return duration.getSeconds();
    }

    public void stop()
    {
        executorService.shutdown();
        try {
            executorService.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException ex) {
            Logger.getLogger(MyTaskExecutor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

বিঃদ্রঃ:

  • MyTaskফাংশন সহ একটি ইন্টারফেস execute
  • থামার সময় ScheduledExecutorService, সর্বদা এটির অনুরোধ করার awaitTerminationপরে ব্যবহার shutdownকরুন: আপনার কাজটি আটকে / অচল হয়ে যাওয়ার সম্ভাবনা থাকে এবং ব্যবহারকারী চিরকাল অপেক্ষা করেন wait

পূর্বের উদাহরণটি আমি ক্যালেন্ডারের সাথে দিয়েছিলাম কেবল একটি ধারণা যা আমি উল্লেখ করেছি, আমি সঠিক সময় গণনা এবং দিবালোক সংরক্ষণের বিষয়গুলি এড়িয়ে চলেছি। @ প্যাডিডি-র অভিযোগের ভিত্তিতে সমাধান আপডেট করেছেন


পরামর্শের জন্য ধন্যবাদ, আপনি দয়া করে আমাকে বিস্তারিত ব্যাখ্যা করতে পারবেন কীভাবে তার intDelayInHourমানে যে আমি সকাল 5 টায় আমার কাজটি পরিচালনা করব?
একিউইবি

অ্যাডেটের উদ্দেশ্য কী?
জোসে আন্দিয়াস

তবে আপনি যদি এইচএইচ: মিমি থেকে এটি শুরু করেন তবে কাজটি সকাল 5 টা বিপরীতে 05: মিমি চালানো হবে? ওপি অনুরোধ অনুসারে এটি দিবালোকের সময় সাশ্রয়ের জন্যও অ্যাকাউন্ট করে না। ঠিক আছে আপনি যদি ঘন্টাখানেক পরে তা শুরু করে থাকেন, বা আপনি যদি 5 থেকে 6 এর মধ্যে যে কোনও সময় খুশি হন, বা ঘড়ির পরিবর্তন হওয়ার পরে বছরের মাঝামাঝি রাতে অ্যাপ্লিকেশনটি পুনরায় চালু করতে আপনার আপত্তি না থাকে তবে আমি মনে করি ...
ধান

4
আপনার এখনও সমস্যা রয়েছে যার মাধ্যমে আপনার যদি সঠিক স্থানীয় সময়টি চালানো চান তবে আপনাকে বছরে দুবার এটি পুনরায় চালু করতে হবে। scheduleAtFixedRateআপনি সারা বছর একই ইউটিসির সময় নিয়ে খুশি না হলে এটি কাটবে না।
প্যাডিডি

4
নীচের উদাহরণটি (দ্বিতীয়) ট্রিগার এন বার বা দ্বিতীয় পাস হওয়া পর্যন্ত চালায় কেন? কোডটি কি প্রতিদিন একবার করে কাজটি ট্রিগার করার কথা ছিল না?
krizajb

25

জাভা 8 তে:

scheduler = Executors.newScheduledThreadPool(1);

//Change here for the hour you want ----------------------------------.at()       
Long midnight=LocalDateTime.now().until(LocalDate.now().plusDays(1).atStartOfDay(), ChronoUnit.MINUTES);
scheduler.scheduleAtFixedRate(this, midnight, 1440, TimeUnit.MINUTES);

14
পঠনযোগ্যতার জন্য আমি TimeUnit.DAYS.toMinutes(1)"ম্যাজিক নম্বর" 1440 এর পরিবর্তে পরামর্শ দেব
পরকীয়

ধন্যবাদ, ভিক্টর এইভাবে যদি আমি স্থানীয় স্থানীয় সময়টি চালাতে চাই তবে বছরে দুবার পুনরায় চালু করা দরকার?
invzbl3

স্থানীয় সময় পরিবর্তিত হওয়ার পরে, নির্দিষ্ট হারটি পরিবর্তন করা উচিত নয়, তৈরি হওয়ার পরে, এটি হারটি হয়ে যায়।
ভিক্টর

23:59:59 এ কীভাবে এটি আমার কাজটিকে ট্রিগার করে?
krizajb

পঠনযোগ্যতার জন্য আমি 1440 বা টাইমউনিট.ডিএইএসএস টোমিনুটস (1) এর পরিবর্তে 1 টি পরামর্শ দেব এবং তারপরে টাইম ইউনিট টাইমউনিত.ডি.ওয়াই.এস. ;-)
কেলি ডেনি

7

আপনার যদি জাভা 8 ব্যবহার করতে সক্ষম হওয়ার বিলাসিতা না থাকে তবে নিম্নলিখিতগুলি আপনার যা প্রয়োজন তা করবে:

public class DailyRunnerDaemon
{
   private final Runnable dailyTask;
   private final int hour;
   private final int minute;
   private final int second;
   private final String runThreadName;

   public DailyRunnerDaemon(Calendar timeOfDay, Runnable dailyTask, String runThreadName)
   {
      this.dailyTask = dailyTask;
      this.hour = timeOfDay.get(Calendar.HOUR_OF_DAY);
      this.minute = timeOfDay.get(Calendar.MINUTE);
      this.second = timeOfDay.get(Calendar.SECOND);
      this.runThreadName = runThreadName;
   }

   public void start()
   {
      startTimer();
   }

   private void startTimer();
   {
      new Timer(runThreadName, true).schedule(new TimerTask()
      {
         @Override
         public void run()
         {
            dailyTask.run();
            startTimer();
         }
      }, getNextRunTime());
   }


   private Date getNextRunTime()
   {
      Calendar startTime = Calendar.getInstance();
      Calendar now = Calendar.getInstance();
      startTime.set(Calendar.HOUR_OF_DAY, hour);
      startTime.set(Calendar.MINUTE, minute);
      startTime.set(Calendar.SECOND, second);
      startTime.set(Calendar.MILLISECOND, 0);

      if(startTime.before(now) || startTime.equals(now))
      {
         startTime.add(Calendar.DATE, 1);
      }

      return startTime.getTime();
   }
}

এটি কোনও বাহ্যিক libs প্রয়োজন হয় না, এবং দিবালোকের সঞ্চয় জন্য অ্যাকাউন্ট হবে। দিনের যে কোনও সময় আপনি টাস্কটিকে একটি Calendarঅবজেক্ট হিসাবে চালাতে চান এবং সেই হিসাবে টাস্কটিকে একটি হিসাবে সীমাবদ্ধ করুন Runnable। উদাহরণ স্বরূপ:

Calendar timeOfDay = Calendar.getInstance();
timeOfDay.set(Calendar.HOUR_OF_DAY, 5);
timeOfDay.set(Calendar.MINUTE, 0);
timeOfDay.set(Calendar.SECOND, 0);

new DailyRunnerDaemon(timeOfDay, new Runnable()
{
   @Override
   public void run()
   {
      try
      {
        // call whatever your daily task is here
        doHousekeeping();
      }
      catch(Exception e)
      {
        logger.error("An error occurred performing daily housekeeping", e);
      }
   }
}, "daily-housekeeping");

এনবি টাইমার টাস্কটি একটি ডেমন থ্রেডে চালিত হয় যা কোনও আইও করার জন্য প্রস্তাবিত নয়। যদি আপনাকে কোনও ব্যবহারকারী থ্রেড ব্যবহার করতে হয় তবে আপনাকে অন্য একটি পদ্ধতি যুক্ত করতে হবে যা টাইমার বাতিল করে।

আপনার যদি কোনও ব্যবহার ScheduledExecutorServiceকরতে হয় তবে কেবল startTimerপদ্ধতিটি নিম্নলিখিতটিতে পরিবর্তন করুন :

private void startTimer()
{
   Executors.newSingleThreadExecutor().schedule(new Runnable()
   {
      Thread.currentThread().setName(runThreadName);
      dailyTask.run();
      startTimer();
   }, getNextRunTime().getTime() - System.currentTimeMillis(),
   TimeUnit.MILLISECONDS);
}

আমি আচরণ সম্পর্কে নিশ্চিত নই তবে আপনার যদি একটি স্টপ পদ্ধতির প্রয়োজন হতে পারে যা shutdownNowআপনাকে ScheduledExecutorServiceরুটে নেমে যাওয়ার সময় কল করে , অন্যথায় আপনি যখন এটি বন্ধ করার চেষ্টা করবেন তখন আপনার অ্যাপ্লিকেশন স্তব্ধ হয়ে যেতে পারে।


আমি তোমার ক্থা বুঝেছি. +1 এবং আপনাকে ধন্যবাদ। তবে, আমরা যদি ডেমন থ্রেড (অর্থাত্‍ new Timer(runThreadName, true)) ব্যবহার না করি তবে ভাল ।
সেজে

@ সেজে কোনও উদ্বেগ নেই। আপনি কোনও আইও না করে থাকলে ডেমন থ্রেডটি ভাল। আমি এটির জন্য যে ব্যবহারের বিষয়টি লিখেছিলাম তা হ'ল একটি সাধারণ অগ্নি-বিস্মৃত শ্রেণীর যা কিছু দৈনিক গৃহকর্ম সম্পাদন করার জন্য কিছু থ্রেড লাথি মেরেছিল। আমি মনে করি আপনি যদি টাইমার টাস্ক থ্রেডে ডাটাবেস পড়ছেন, যেমন ওপি এর অনুরোধটি সূচিত করে, তবে আপনার কোনও ডেমোন ব্যবহার করা উচিত নয় এবং আপনার অ্যাপ্লিকেশনটি বন্ধ করতে সক্ষম হওয়ার জন্য আপনাকে কোনও ধরণের স্টপ পদ্ধতির প্রয়োজন হবে। stackoverflow.com/questions/7067578/...
PaddyD

@ প্যাডিডি শেষ অংশটি ছিল অর্থাৎ শিডিউডএকসিকিউটর সার্ভিসটি ব্যবহার করা সঠিক ছিল ??? বেনাম শ্রেণি তৈরির পদ্ধতিটি সঠিক বাক্য গঠন বুদ্ধিমান দেখাচ্ছে না। এছাড়াও NewSingleThreadExecutor () এর সময়সূচী পদ্ধতিটি সঠিক হবে না ??
ফ্রিজ এফআরানসিস

6

আপনি কি কোয়ার্টজ শিডিয়ুলারের মতো কিছু ব্যবহার করার কথা বিবেচনা করেছেন ? এই লাইব্রেরিতে প্রতিদিন একটি নির্ধারিত সময়ে এক্সপ্রেশনের মতো ক্রোন ব্যবহার করে সময় নির্ধারণের জন্য কর্মসূচি নির্ধারণের জন্য একটি পদ্ধতি রয়েছে (একবার দেখুন CronScheduleBuilder)।

কিছু উদাহরণ কোড (পরীক্ষিত নয়):

public class GetDatabaseJob implements InterruptableJob
{
    public void execute(JobExecutionContext arg0) throws JobExecutionException
    {
        getFromDatabase();
    }
}

public class Example
{
    public static void main(String[] args)
    {
        JobDetails job = JobBuilder.newJob(GetDatabaseJob.class);

        // Schedule to run at 5 AM every day
        ScheduleBuilder scheduleBuilder = 
                CronScheduleBuilder.cronSchedule("0 0 5 * * ?");
        Trigger trigger = TriggerBuilder.newTrigger().
                withSchedule(scheduleBuilder).build();

        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.scheduleJob(job, trigger);

        scheduler.start();
    }
}

আরও কিছুটা কাজ সামনের দিকে রয়েছে এবং আপনাকে আপনার চাকরি সম্পাদনের কোডটি আবারও লেখার দরকার হতে পারে তবে আপনি কীভাবে কাজ চালাতে চান তার উপর এটি আপনাকে আরও নিয়ন্ত্রণ দেয়। এছাড়াও আপনার প্রয়োজন অনুসারে শিডিউল পরিবর্তন করা সহজ হবে।


5

জাভা 8:
শীর্ষ উত্তর থেকে আমার আপগ্রেজ সংস্করণ:

  1. নিষ্ক্রিয় থ্রেড সহ থ্রেডপুলের কারণে ওয়েব অ্যাপ্লিকেশন সার্ভার যখন থামতে চায় না তখন স্থির পরিস্থিতি
  2. পুনরাবৃত্তি ছাড়া
  3. আপনার কাস্টম স্থানীয় সময় দিয়ে টাস্ক চালান, আমার ক্ষেত্রে এটি বেলারুশ, মিনস্ক


/**
 * Execute {@link AppWork} once per day.
 * <p>
 * Created by aalexeenka on 29.12.2016.
 */
public class OncePerDayAppWorkExecutor {

    private static final Logger LOG = AppLoggerFactory.getScheduleLog(OncePerDayAppWorkExecutor.class);

    private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

    private final String name;
    private final AppWork appWork;

    private final int targetHour;
    private final int targetMin;
    private final int targetSec;

    private volatile boolean isBusy = false;
    private volatile ScheduledFuture<?> scheduledTask = null;

    private AtomicInteger completedTasks = new AtomicInteger(0);

    public OncePerDayAppWorkExecutor(
            String name,
            AppWork appWork,
            int targetHour,
            int targetMin,
            int targetSec
    ) {
        this.name = "Executor [" + name + "]";
        this.appWork = appWork;

        this.targetHour = targetHour;
        this.targetMin = targetMin;
        this.targetSec = targetSec;
    }

    public void start() {
        scheduleNextTask(doTaskWork());
    }

    private Runnable doTaskWork() {
        return () -> {
            LOG.info(name + " [" + completedTasks.get() + "] start: " + minskDateTime());
            try {
                isBusy = true;
                appWork.doWork();
                LOG.info(name + " finish work in " + minskDateTime());
            } catch (Exception ex) {
                LOG.error(name + " throw exception in " + minskDateTime(), ex);
            } finally {
                isBusy = false;
            }
            scheduleNextTask(doTaskWork());
            LOG.info(name + " [" + completedTasks.get() + "] finish: " + minskDateTime());
            LOG.info(name + " completed tasks: " + completedTasks.incrementAndGet());
        };
    }

    private void scheduleNextTask(Runnable task) {
        LOG.info(name + " make schedule in " + minskDateTime());
        long delay = computeNextDelay(targetHour, targetMin, targetSec);
        LOG.info(name + " has delay in " + delay);
        scheduledTask = executorService.schedule(task, delay, TimeUnit.SECONDS);
    }

    private static long computeNextDelay(int targetHour, int targetMin, int targetSec) {
        ZonedDateTime zonedNow = minskDateTime();
        ZonedDateTime zonedNextTarget = zonedNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec).withNano(0);

        if (zonedNow.compareTo(zonedNextTarget) > 0) {
            zonedNextTarget = zonedNextTarget.plusDays(1);
        }

        Duration duration = Duration.between(zonedNow, zonedNextTarget);
        return duration.getSeconds();
    }

    public static ZonedDateTime minskDateTime() {
        return ZonedDateTime.now(ZoneId.of("Europe/Minsk"));
    }

    public void stop() {
        LOG.info(name + " is stopping.");
        if (scheduledTask != null) {
            scheduledTask.cancel(false);
        }
        executorService.shutdown();
        LOG.info(name + " stopped.");
        try {
            LOG.info(name + " awaitTermination, start: isBusy [ " + isBusy + "]");
            // wait one minute to termination if busy
            if (isBusy) {
                executorService.awaitTermination(1, TimeUnit.MINUTES);
            }
        } catch (InterruptedException ex) {
            LOG.error(name + " awaitTermination exception", ex);
        } finally {
            LOG.info(name + " awaitTermination, finish");
        }
    }

}

4
আমারও অনুরূপ প্রয়োজন আছে। আমাকে নির্দিষ্ট সময়ে এক দিনের জন্য টাস্ক নির্ধারণ করতে হবে। নির্ধারিত টাস্কটি সম্পূর্ণ হয়ে গেলে, পরবর্তী সময়ে পরবর্তী দিনের জন্য শিডিয়ুল টাস্ক। এটি অব্যাহত রাখা উচিত M আমার প্রশ্নটি নির্ধারিত কাজটি কীভাবে সম্পন্ন হয়েছে তা কীভাবে খুঁজে পাওয়া যায়। একবার আমি জানলাম তফসিলের কাজটি শেষ হয়ে গেছে তবে কেবলমাত্র আমি পরের দিনের জন্য সময়সূচী করতে পারি।
amitwd

2

আমারও একই সমস্যা ছিল। আমি যে কাজগুলো একটি দিন ব্যবহার করার সময় মৃত্যুদন্ড কার্যকর করা উচিত সময়তালিকা গুচ্ছ ছিল ScheduledExecutorService। এটি তার বর্তমান সময়ে তুলনামূলকভাবে অন্যান্য সমস্ত কাজগুলির নির্ধারিত সময়টি 3:30 টা থেকে শুরু করে একটি কাজ দ্বারা সমাধান করা হয়েছিল । এবং পরের দিন সকাল সাড়ে তিনটায় নিজেকে পুনরায় নির্ধারণ করুন।

এই দৃশ্যের সাথে দিবালোক সঞ্চয় এখন আর কোনও সমস্যা নয়।


2

আপনি একটি সাধারণ তারিখ বিশ্লেষণ ব্যবহার করতে পারেন, দিনের সময় যদি এখন আগে হয় তবে আসুন আগামীকাল শুরু করুন:

  String timeToStart = "12:17:30";
  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss");
  SimpleDateFormat formatOnlyDay = new SimpleDateFormat("yyyy-MM-dd");
  Date now = new Date();
  Date dateToStart = format.parse(formatOnlyDay.format(now) + " at " + timeToStart);
  long diff = dateToStart.getTime() - now.getTime();
  if (diff < 0) {
    // tomorrow
    Date tomorrow = new Date();
    Calendar c = Calendar.getInstance();
    c.setTime(tomorrow);
    c.add(Calendar.DATE, 1);
    tomorrow = c.getTime();
    dateToStart = format.parse(formatOnlyDay.format(tomorrow) + " at " + timeToStart);
    diff = dateToStart.getTime() - now.getTime();
  }

  ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);            
  scheduler.scheduleAtFixedRate(new MyRunnableTask(), TimeUnit.MILLISECONDS.toSeconds(diff) ,
                                  24*60*60, TimeUnit.SECONDS);

1

শুধু ভিক্টরের উত্তর যোগ করতে ।

আমি ভেরিয়েবল (তার ক্ষেত্রে দীর্ঘ midnight) এর চেয়ে বেশি হলে এটি দেখতে একটি চেক যুক্ত করার পরামর্শ দেব 1440। যদি তা হয় তবে আমি তা বাদ দেব .plusDays(1), অন্যথায় টাস্কটি কেবল আগামীকাল পরের দিন চলবে।

আমি এটি সহজভাবে এটি করেছি:

Long time;

final Long tempTime = LocalDateTime.now().until(LocalDate.now().plusDays(1).atTime(7, 0), ChronoUnit.MINUTES);
if (tempTime > 1440) {
    time = LocalDateTime.now().until(LocalDate.now().atTime(7, 0), ChronoUnit.MINUTES);
} else {
    time = tempTime;
}

আপনি যদি ব্যবহার করেন তবে এটি সরল করে তোলেtruncatedTo()
মার্ক জেরোনিমাস

1

নিম্নলিখিত উদাহরণটি আমার জন্য কাজ করে

public class DemoScheduler {

    public static void main(String[] args) {

        // Create a calendar instance
        Calendar calendar = Calendar.getInstance();

        // Set time of execution. Here, we have to run every day 4:20 PM; so,
        // setting all parameters.
        calendar.set(Calendar.HOUR, 8);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.AM_PM, Calendar.AM);

        Long currentTime = new Date().getTime();

        // Check if current time is greater than our calendar's time. If So,
        // then change date to one day plus. As the time already pass for
        // execution.
        if (calendar.getTime().getTime() < currentTime) {
            calendar.add(Calendar.DATE, 1);
        }

        // Calendar is scheduled for future; so, it's time is higher than
        // current time.
        long startScheduler = calendar.getTime().getTime() - currentTime;

        // Setting stop scheduler at 4:21 PM. Over here, we are using current
        // calendar's object; so, date and AM_PM is not needed to set
        calendar.set(Calendar.HOUR, 5);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.AM_PM, Calendar.PM);

        // Calculation stop scheduler
        long stopScheduler = calendar.getTime().getTime() - currentTime;

        // Executor is Runnable. The code which you want to run periodically.
        Runnable task = new Runnable() {

            @Override
            public void run() {

                System.out.println("test");
            }
        };

        // Get an instance of scheduler
        final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        // execute scheduler at fixed time.
        scheduler.scheduleAtFixedRate(task, startScheduler, stopScheduler, MILLISECONDS);
    }
}

তথ্যসূত্র: https://chynten.wordpress.com/2016/06/03/java-scheduler-to-run-every-day-on-specific-time/


1

আপনি প্রতিদিন নির্দিষ্ট সময় আপনার টাস্ক নির্ধারণ করতে ক্লাসের নীচে ব্যবহার করতে পারেন

package interfaces;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class CronDemo implements Runnable{

    public static void main(String[] args) {

        Long delayTime;

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        final Long initialDelay = LocalDateTime.now().until(LocalDate.now().plusDays(1).atTime(12, 30), ChronoUnit.MINUTES);

        if (initialDelay > TimeUnit.DAYS.toMinutes(1)) {
            delayTime = LocalDateTime.now().until(LocalDate.now().atTime(12, 30), ChronoUnit.MINUTES);
        } else {
            delayTime = initialDelay;
        }

        scheduler.scheduleAtFixedRate(new CronDemo(), delayTime, TimeUnit.DAYS.toMinutes(1), TimeUnit.MINUTES);

    }

    @Override
    public void run() {
        System.out.println("I am your job executin at:" + new Date());
    }
}

4
পুরানো Dateএবং TimeUnit2019 সালে ব্যবহার করবেন না
মার্ক জেরোনিমাস

0

যদি আপনার সার্ভারটি 4:59 AM এ নেমে যায় এবং 5:01 এ ফিরে আসে? আমি মনে করি এটি কেবল রান এড়িয়ে যাবে। আমি কোয়ার্টজের মতো ধ্রুবক শিডিয়ুলারের পরামর্শ দেব, এটির শিডিয়ুল ডেটা কোথাও সঞ্চয় করবে। তারপরে এটি দেখতে পাবে যে এই রানটি এখনও সম্পাদিত হয়নি এবং এটি 5:01 AM-এ করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.