Java 每月计时器

标签 java multithreading timer

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

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

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 上完成后,该线程和对象是否会被垃圾回收处理?随着时间的推移,我不想建立一堆什么都不做但不会被删除的线程。也许我对线程和定时器的工作原理没有正确的理解......

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

谢谢!

最佳答案

如果您担心创建不需要的对象,您总是可以创建一个对象,该对象又会创建/“销毁”所有引用,因此创建的对象可能会被 gc'ed。

在最坏的情况下,一年内您将有 12 个不需要的对象,我认为这是可以忍受的。你的担心仍然是有道理的。

这是我在执行结束时按照 Joel 的时间表建议进行的尝试。注意,当前的 Timer 被一个新的 Timer 替换了,所以,timer 和 timer task 都可以被 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 每月计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4107011/

相关文章:

javascript - 数据库获取后便士拍卖计时器更新

java - 如何从 Java 控制台应用程序中的扫描器读取字符串?

java - 正则表达式匹配 url 目录路径而不匹配文件名

java - Spring MVC JavaConfig webapp中的"error-page"配置? (没有 web.xml)

c - Windows 线程 - 调试工作版本没有 - 尝试在线程启动时从线程获取值

c# - 为计时器组件设置初始小时

java - JSON在屏幕上的读取和打印

c - 多线程信号量程序

C++11代替 `GetExitCodeThread`监控线程状态?

windows - 需要产生稳定的 10mSec 中断