Forcing Thread to execute an operation every day at specific time

时间:2016-03-02 10:53:07

标签: java multithreading

As part of an assignment to build a coupon system I'm working on an assignment to build a Java program to support coupon system database. I'm supposed to create a Thread that runs a task at the beginning of every day (00:00:00 or a bit later) that checks which of the coupons in the database expired and removes them from database. For this I can't use java libs and packages that implement schedulers and timers. I'm struggling to find a way to assure that the task runs every day at the specific time it needs to be.

Here is what I came up with till now (it will only work in 24 hours intervals):

    public class DailyCouponExpirationTask extends Thread {

        // class fields
        private boolean keepRunning;
        private final long sleepTime;
        private CompanyDBDAO companyDBDAO;
        private CouponDBDAO couponDBDAO;
        private CustomerDBDAO customerDBDAO;

        // constructor
        DailyCouponExpirationTask() {
            keepRunning = true;
            this.sleepTime = 24 * 60 * 60 * 1000;
            companyDBDAO = new CompanyDBDAO();
            couponDBDAO = new CouponDBDAO();
            customerDBDAO = new CustomerDBDAO();
        } // end constructor

        // class methods
        // force the thread to stop
        void stopRunning() {
            keepRunning = false;

            interrupt();
        } // end method stopRunning

        // Runnable interface methods
        // run 
        @Override
        public void run() {
            while (keepRunning) {
                Date currentDate = new Date(new java.util.Date().getTime());
                Collection<Coupon> coupons = couponDBDAO.getAllCoupons();

                Iterator<Coupon> iterator = coupons.iterator();

                while (iterator.hasNext()) {
                    Coupon currentCoupon = iterator.next();

                    if (currentDate.after(currentCoupon.getEndDate())) {
                        // remove coupon from database
                    }
                }

                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    if (keepRunning) {
                        e.printStackTrace();
                    }
                }
            }
        } // end method run

    } // end class DailyCouponExpirationTask

Thanks in advance!

EDIT: I've come up with a solution and I would like to hear your thoughts and comments about it. I'v created a method to calculate the overall sleep time of the Thread until next routine task iteration:

// calculate sleep time until next coupons update task (1:00:00 next day)
private long calculateSleepTime() {
    Calendar currentTime = new GregorianCalendar();
    Calendar nextUpdateTime = new GregorianCalendar();

    nextUpdateTime.set(Calendar.HOUR_OF_DAY, 1);
    nextUpdateTime.set(Calendar.MINUTE, 0);
    nextUpdateTime.set(Calendar.SECOND, 0);
    nextUpdateTime.set(Calendar.MILLISECOND, 0);

    nextUpdateTime.add(Calendar.DAY_OF_MONTH, 1);

    return nextUpdateTime.getTimeInMillis() - currentTime.getTimeInMillis();
} // end method calculateSleepTime 

2 个答案:

答案 0 :(得分:1)

使用Date类,只需使用substring方法获取星期几并检查它是否相同。如果不是那么新的一天到了。

以下是您的run方法的样子:

public void run(){
 while(true){

   Date d=new Date();
 String day=d.toString().substring(0,3);
 for(;;){
try{
Thread.sleep(60000);
 Date date=new Date();
 String currentday=date.toString().substring(0,3);
 if(day.equals(currentday)==false){break;}
}catch(Exception e){System.out.println(e.getMessage());}
  Date d=new Date();

}
//Do things once a day
}
}

希望这有助于:)

答案 1 :(得分:1)

我不确定你是否可以100%确定一个线程在指定的时间完全运行(它取决于许多因素,如操作系统,系统负载等)。 话虽如此,请专门针对scheduleAtFixedRate方法查看ScheduledExecutorService。它提供了一个API来定期执行计划。例如,你可以这样做:

    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    long initialDelay = 1800;
    long period = 3600;
    TimeUnit timeUnit = TimeUnit.SECONDS;
    executor.scheduleAtFixedRate(new Runnable() {
        @Override public void run() {
            //do something here
        }
    }, initialDelay, period, timeUnit);

这样做,安排在1800秒后执行任务,然后每3600秒重复一次。 您必须记住,对于要执行的计划操作,JVM必须保持运行。

我强烈建议浏览java.util.concurrent包的javadoc。你会在那里找到很多好东西。