Java月计时器 [英] Java Monthly Timer

查看:120
本文介绍了Java月计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个将在每个月的同一天运行的Timer / TimerTask。我无法安排重复计时器,因为一个月不会总是相同的时间长度。

I am trying to create a Timer/TimerTask that will run the same day of every month. I can't schedule a repeating Timer because a month won't always be the same lenght of time.

所以,这是我的解决方案:

So, here 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
    }
}

我认为我将遇到的问题是因为第一个TimerTask创建了第二个Timer,第一个Timer是否会被保留,因为它创建了第二个?代码在第一个Timer完成后,是否会通过垃圾回收来处理该线程和对象?随着时间的推移,我不想建立一堆没有做任何事情但没有被删除的线程。也许我对Threads和Timers的运作方式没有正确的理解...

The problem I think I'm going to run into is that because the first TimerTask creates the second Timer, will the first Timer be kept around because it created the second? After the code finishes on the first Timer, will that thread and object be taken care of by garbage collection? Over time I don't want to build up a bunch of Threads that aren't doing anything but aren't being removed. Maybe I don't have a proper understanding of how Threads and Timers work...

我愿意接受其他方法建议每月计时器的建议我不必使用第三方JAR。

I'm open to suggestions of other ways to create a monthly timer as long as I don't have to use third party JARs.

谢谢!

推荐答案

如果你担心的是创建不需要的对象,你总是可以创建一个对象,然后创建/销毁所有引用,因此创建的对象可能是gc'ed。

If what worries you is to create unneeded objects you can alway create an object which in turn creates/"destroy" all the references, so the objects created may be gc'ed.

在最糟糕的情况下,一年内你会有12个不需要的物品,我认为这是可以忍受的。您的担忧仍然有效。

In the worst case, you'll have 12 unneeded objects in a year, which, I think is bearable. Still your concern is valid.

这是我在执行结束后跟随Joel建议的计划。注意,当前的Timer被一个新的替换,因此,定时器和定时器任务都可以是gc'ed。

Here's my attempt following Joel's suggestion of schedule at the end of the execution. Notice, the current Timer is replaced by a new one, so, both, the timer and the timer task could 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, 0);
        runDate.add(Calendar.MONTH, 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();

    }
}

这篇关于Java月计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆