当前位置: 首页 > 面试题库 >

Java月度计时器

宋明亮
2023-03-14
问题内容

我正在尝试创建一个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?代码在第一个Timer上完成之后,垃圾回收会处理该线程和对象吗?随着时间的流逝,我不想建立一堆什么也不做但没有被删除的线程。也许我对线程和计时器的工作方式没有足够的了解…

只要我不必使用第三方JAR,就可以接受其他方式创建月度计时器的建议。

谢谢!


问题答案:

如果您担心要创建不需要的对象,则可以始终创建一个对象,该对象又会创建/“销毁”所有引用,因此可以对创建的对象进行通用控制。

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

这是我在执行死刑后按照乔尔的时间表建议进行的尝试。注意,当前的Timer被新的Timer取代,因此,可以对timer和timer任务进行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中的精度为15-16毫秒?我该如何解决? 问题答案: 您是否尝试过使用System.nanoTime()? 从Javadoc: 返回最精确的可用系统计时器的当前值,以纳秒为单位。 此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示自某个固

  • 我想计算两个日期之间的时间跨度(注意:输入格式为dd.MM.yyyy,请参见下面的代码)。特别的是,我们不想每个月用30天,一年用360天。我更希望在“人类模式”上有所不同(不知道如何称呼它)。 比方说,我想计算从2014年10月1日到2015年3月17日的差异(包括最后一天)。从10月到2月是5个月。然后剩下的是18天(从第1天到17天,包括第17天)。所以结果应该是: 0年5个月18天 当然,

  • 问题内容: 在代码的第四行(忽略空格和注释),然后我计算两个日期之间的月份差。这行得通,但看起来有些古怪。有没有更好的办法? 问题答案:

  • 问题内容: 我正在尝试使用计时器来安排应用程序中的重复事件。但是,我希望能够实时调整事件的触发时间(根据用户输入)。 例如: 然后,我启动此类的新实例并调用其set period函数。但是,当我这样做时,我得到了一个非法状态异常。您可以看到System.out.println(timer);。在那儿,因为我正在检查,并且足够肯定,它们是两个不同的计时器……所以,当我尝试在全新的Timer实例上运行

  • ScheduledExecutorService的推荐用途之一是直接替代Timer类,如许多主题中所述: Java定时器与执行器服务 TimerTask和Executors之间的差异。newScheduledThreadPool(1) scheduleAtFixedRate和scheduleAtFixedRate之间有什么区别 Android计时器计划与scheduleAtFixedRate 但是