本帖最后由 King520754 于 2011-03-27 14:52:01 编辑

解决方案 »

  1.   

    直接把timer设置成24小时的放到初始化里
      

  2.   

    你这个需要解决的问题称为 time-critical 
    我们平时所用的JVM无法解决你的这个问题   道理很简单  你觉得timer帮你跑一边 long delayTime = 24*60*60*1000; 的精度有多准。不过有一部分人正奋斗在这个time-critical java中,java有另外一个版本叫做 java real-time system
    他是一个还没有实用价值的版本。但是在这个版本中可以做到时间的完全精度化  而且 可以使用像 下周3,12天后,这样的时间计量。有兴趣可以看看 http://java.sun.com/javase/technologies/realtime/index.jsp#jsr-001 
    不过目前没有太大的实用价值
      

  3.   

    我问题描述出了点问题:请教:如何能让执行的更精确一些.
      现在已经有2个问题了.
      1.可能会执行任务.
    --->应该是:一天内可能会执行多次任务.
        因为启动时过了指定的时间,就会立即执行.
        
        我现在想到的办法:只有把指定的晚一点.比如指定到23:50分这个样子.  2.下次执行任务时间会被更改.
    --->任务执行间隔,以上次为准.
      

  4.   

    Timer作为一个属性存在,设置一个相应的set方法

    setxxx(Date date) {
        if (time == null) {...}
        else {timer.cancel();}
        timer.schedule(task, date,delayTime); 
    }
    当重启时,setxxx(new Date()),指定启动时 setxxx(sometime);
      

  5.   

    如果当天的时间已经过了,而你又不想让定时任务立即执行,可以判断下时间,让它第二天再执行://判断今天的执行时间是否已经过去,如果过去则改为明天
    if (date.getTime() < System.currentTimeMillis()) {
        date = new Date(date.getTime() + 24 * 60 * 60 * 1000);
    }Timer timer = new Timer();
    if (configSerial()) {
        timer.schedule(new MyTimerTask(), date, 24 * 60 * 60 * 1000);
        showRunningDialog(timer);
    }
      

  6.   

    定时执行这类任务还是操作系统的强项,应用层没必要关心太多底层时间时区这些细节在Unix上用cronjob,Windows上用at,你的问题可以很容易解决
      

  7.   

    Java 里面要实现这样的定时任务还有比较麻烦的,不建议自己去实现,把 Quartz 这个框架的 jar 加进来吧。对于你的这个用途,只用 Quartz 就可以了,不需要用什么 Spring 集成的。如果需要自己实的话,可以使用 java.util.concurrent.DelayQueue,这个称为延迟队列,是 Java 集合框架的实现之一。存放进去的对象必须实现 java.util.concurrent.Delayed 和 java.lang.Comparable<T> 接口。在 Delayed 接口实现 public long getDelay(TimeUnit unit) 方法,如果在计算时返回值是小于等于 0 的话,那么在 DelayQueue 中使用 take 方法可以将其取出来。我们可以在第一次往 DelayQueue 塞任务的时候,把下一次要执行的毫秒保存到这个任务对象中去。等时间一到,那 take 由阻塞状态变为运行状态,会将其中超时的对象取出来。取出来之后,计算下一次运行的毫秒数,再将这个对象塞回队列中去,同时在外部还有这个对象的引用,使用 ExecuteService 接口 submit 执行一次。自己要实现这样的任务调度非常麻烦。这个是我写的小例子作为参考(没有使用 ScheduledExecutorService 类)。任务调度时间是每分钟执行一次(为了便利起见,全写在一个 java 文件中了)。import java.util.Calendar;
    import java.util.concurrent.DelayQueue;
    import java.util.concurrent.Delayed;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;public class DelayQueueTest {    public static void main(String[] args) throws InterruptedException {        SchedulerManager manager = new SchedulerManager();
            manager.addJob(new EveryMinuteDelay(new MyJob()));
            manager.start();        printCurrentTime();
            sleepMinutes(3);           // 休息 3 分钟后关掉
            manager.stop();     // 停止工作
            printCurrentTime();
        }    private static void sleepMinutes(long minutes) {
            try {
                TimeUnit.MINUTES.sleep(minutes);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }    private static void printCurrentTime() {
            System.out.printf("Current: %tF %<tT%n", System.currentTimeMillis());
        }
    }/**
     * <p>任务调度管理器</p>
     *
     * 2010-5-28 下午11:30:20
     */
    class SchedulerManager {    private ExecutorService executor;
        private DelayQueue<JobDelayed> jobs;
        private Scheduler scheduler;    public SchedulerManager() {
            this(1);
        }    /**
         * 根据线程池中线程数量构造调度管理器
         * @param threadPool
         */
        public SchedulerManager(int threadPool) {
            this.jobs = new DelayQueue<JobDelayed>();
            // 由于调度管理器需要占用一个线程,因此需要加 1
            this.executor = Executors.newFixedThreadPool(threadPool + 1);
            this.scheduler = new Scheduler(this);
        }    /**
         * <p>添加需要计划的任务</p>
         *
         * @param job
         */
        public void addJob(JobDelayed jobDelayed) {
            jobDelayed.nextTime();  // 计算下一次执行的时间
            jobs.put(jobDelayed);   // 添加到延迟队列中去
        }    public void start() {
            scheduler.start();  // 启动任务调度器
        }    public void stop() {
            scheduler.stop();  // 停止任务调度器
        }    private void execute() throws InterruptedException {
            submit(take());
        }    /**
         * <p>将任务提交给线程池去执行</p>
         *
         * @param task
         */
        private void submit(Runnable task) {
            executor.submit(task);
        }    /**
         * <p>强制停止工作</p>
         */
        private void shutdown() {
            executor.shutdown();
        }    /**
         * <p>获取到时间的任务,如果该任务下一次还需要执行,将该任务加回队列中去。</p>
         *
         * @return
         * @throws InterruptedException
         */
        private JobDelayed take() throws InterruptedException {
            JobDelayed jobDelayed = jobs.take();
            if(jobDelayed.hasNext()) {
                addJob(jobDelayed);
            }
            return jobDelayed;
        }    /**
         * <p>调度器</p>
         * 2010-5-28 下午11:40:58
         */
        private static class Scheduler implements Runnable {        private SchedulerManager manager;
            private boolean running = false;        /**
             * 使用调度管理器构造
             * @param manager
             */
            public Scheduler(SchedulerManager manager) {
                this.manager = manager;
            }        /**
             * <p>启动该调度器</p>
             */
            public void start() {
                if(!running) {
                    manager.submit(this);
                    this.running = true;
                }
            }        /**
             * 执行任务调度工作
             */
            @Override
            public void run() {
                while(running) {
                    try {
                        manager.execute();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }        /**
             * <p>强制停止该调度器</p>
             */
            public void stop() {
                manager.shutdown();
                running = false;
            }
        }
    }/**
     * <p>需要进行任务调度的工作内容</p>
     */
    interface Job {
        public void execute();
    }/**
     * <p>测试工作,输出当前时间</p>
     */
    class MyJob implements Job {
        public void execute() {
            System.out.printf("JOB OUTPUT: %tF %<tT%n", System.currentTimeMillis());
        }
    }/**
     * <p>需要进行调度工作的任务</p>
     */
    interface JobDelayed extends Delayed, Runnable {    /**
         * <p>计算下一次执行的时间</p>
         */
        public void nextTime();    /**
         * <p>下一次是否需要执行</p>
         */
        public boolean hasNext();
    }/**
     * <p>需要进行每分钟调度工作的任务</p>
     */
    class EveryMinuteDelay implements JobDelayed {    private long nextTime;
        private Job job;    public EveryMinuteDelay(Job job) {
            this.job = job;
        }    public void nextTime() {
            Calendar c = Calendar.getInstance();
            c.set(Calendar.SECOND, 0);
            c.set(Calendar.MILLISECOND, 0);
            c.add(Calendar.MINUTE, 1);
            this.nextTime = c.getTimeInMillis();  // 这个任务的 nextTime 为下一分钟
        }    public boolean hasNext() {
            return true;   // 永远执行下去
        }    @Override
        public long getDelay(TimeUnit unit) {
            return nextTime - System.currentTimeMillis();   // 是否超时
        }    @Override
        public int compareTo(Delayed o) {
            return (int)(o.getDelay(TimeUnit.MILLISECONDS) - getDelay(TimeUnit.MILLISECONDS));
        }    @Override
        public void run() {
            job.execute();   // 执行任务
        }    public String toString() {
            return String.format("next: %tF %<tT", nextTime);
        }
    }
      

  8.   

    基本原理就是首次或者第一次执行时,把下一次执行的时间先计算出来放到 DelayQueue 中去,时间一到用 take 就能立即将其取出。
      

  9.   

    7楼的强.但没有用过.所以,暂时学习一下你的思路,写一些demo.我现在将时间设置成23点,并加时间判断.谢谢各位,结贴了.