Java monthly timer

I'm trying to create a timer / TimerTask that will run on the same day of each month I can't schedule a repeat timer because a month won't always be the same length of time

So this is my solution:

public class MyTask extends TimerTask {
    public void run(){
        //do process file stuff

        if(scheduledExecutionTime() != 0){
            TimerHelper.restartMyTimer();
        }
    }
}

public class TimerHelper {
    public static HashTable timersTable = new HashTable();

    public static void restartMyTimer(){
        Calendar runDate = Calendar.getInstance();
        runDate.set(Calendar.DAY_OF_MONTH,1);
        runDate.set(Calendar.HOUR_OF_DAY,4);
        runDate.set(Calendar.MINUTE,0);
        runDate.add(Calendar.MONTH,1);//set to next month

        MyTask myTask = new MyTask();
        Timer myTimer = new Timer();

        myTimer.schedule(myTask,runDate.getTime());

        timersTable = new HashTable();//keeping a reference to the timer so we 
        timersTable.put("1",myTimer);//have the option to cancel it later
    }
}

I think the problem I will encounter is because the first TimerTask creates the second timer. Will the first timer be retained because it creates the second? After the first timer is completed, will the code process the thread and object through garbage collection? Over time, I don't want to create a bunch of threads that haven't done anything but haven't been deleted Maybe I don't have a correct understanding of how threads and timers work

As long as I don't have to use third-party jars, I can suggest other ways to create monthly timers

thank you!

Solution

If you are worried about creating unnecessary objects, you can always create an object and then create / destroy all references, so the created object may be gc'ed

In the worst case, you will have 12 unnecessary items in a year, which I think is tolerable Your fears are still valid

This is the plan I follow Joel's suggestion after the implementation Note that the current timer is replaced by a new timer, so both timer and timer task can be gc'ed

package monthly.schedule;

import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;
import java.util.Calendar;

public class MonthlyTimer { 
    // What to do
    private final Runnable whatToDo;

    // when 
    private final int dayOfMonth;
    private final int hourOfDay;

    // The current timer
    private Timer current = new Timer();//to avoid NPE

    public void cancelCurrent() { 
        current.cancel();// cancel this execution;
        current.purge(); // removes the timertask so it can be gc'ed
    }

    // create a new instance
    public static MonthlyTimer schedule( Runnable runnable,int dayOfMonth,int hourOfDay ) { 
        return new MonthlyTimer( runnable,dayOfMonth,hourOfDay );
    }

    private MonthlyTimer(Runnable runnable,int day,int hour ) { 
        this.whatToDo = runnable;
        this.dayOfMonth = day;
        this.hourOfDay = hour;
        schedule();
    }
    // Schedules the task for execution on next month. 
    private void schedule() { 
        // Do you mean like this?
        cancelCurrent();
        current = new Timer(); // assigning a new instance
        // will allow the prevIoUs Timer to be gc'ed

        current.schedule( new TimerTask() { 
            public void run() { 
                try { 
                    whatToDo.run();
                } finally { 
                    schedule();// schedule for the next month
                }
            }
        },nextDate() );           
    }
    // Do the next date stuff
    private Date nextDate() { 
        Calendar runDate = Calendar.getInstance();
        runDate.set(Calendar.DAY_OF_MONTH,dayOfMonth);
        runDate.set(Calendar.HOUR_OF_DAY,hourOfDay);
        runDate.set(Calendar.MINUTE,1);//set to next month
        return runDate.getTime();
    }
}

class UseIt { 
    public static void main( String [] args ) { 
        int the1st = 1;
        int at16hrs = 16;

        MonthlyTimer t = MonthlyTimer.schedule( new Runnable() { 
            public void run() { 
                System.out.println( "Hola" );
            }},the1st,at16hrs );

        // will print "Hola" every 1st at 16:00 hrs.
       // if needed you can cancel with: 
        t.cancelCurrent();

    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>