1

所以我想尝试一下 Timer 和 TimerTask 类。

我能够在 30 秒后执行一行代码。我现在一直在尝试做的是让这行代码执行 5 分钟。

这是我最初尝试的

public static void main(String[] args)
{
    for ( int i = 0; i <= 10; i ++ )
    {
        Timer timer = new Timer();
        timer.schedule( new TimerTask()
        {
            public void run()
            {
                System.out.println("30 Seconds Later");
            }
        }, 30000
        );
    }   
}

我在 for 循环中使用了数字 10 来查看 timer.schedule 是否会在循环的下一次迭代中再等待 30 秒。

知道我应该怎么做吗?我尝试使用 schedule 方法和传入的参数 for period ,但这只会使它重新执行并且它从未停止过。

4

5 回答 5

2

Java 在java.util.concurrent包中提供了一组丰富的 API 来实现这些任务。这些 API 之一是ScheduledExecutorService. 例如,考虑下面给出的代码:此代码将每秒执行一次,最多持续几分钟:Runnable task305

import java.util.concurrent.*;

class Scheduler 
{
    private final ScheduledExecutorService service;
    private final long period = 30;//Repeat interval
    public Scheduler()
    {
        service = Executors.newScheduledThreadPool(1);
    }
    public void startScheduler(Runnable runnable)
    {
        final ScheduledFuture<?> handler = service.scheduleAtFixedRate(runnable,0,period,TimeUnit.SECONDS);//Will cause the task to execute after every 30 seconds
        Runnable cancel = new Runnable()
        {
            @Override
            public void run()
            {
                handler.cancel(true);
                System.out.println("5 minutes over...Task is cancelled : "+handler.isCancelled());
            }
        };
        service.schedule(cancel,5,TimeUnit.MINUTES);//Cancels the task after 5 minutes
    }
    public static void main(String st[])
    {
        Runnable task = new Runnable()//The task that you want to run
        {
            @Override
            public void run()
            {
                System.out.println("I am a task");
            }
        };
        Scheduler sc = new Scheduler();
        sc.startScheduler(task);
    }
}     
于 2013-05-08T16:37:30.277 回答
1

您遇到的问题是计划Timer在不同的线程上运行 - 也就是说,for循环的下一次迭代在计划后立即开始运行,而不是 30 秒后。看起来您的代码同时启动了十个计时器,这意味着它们应该在 30 秒后(大约)全部打印一次。

当您尝试使用schedule(带有第三个参数)的重复版本时,您走在了正确的轨道上。正如您所指出的,这不是您想要的,因为它无限期地运行。但是,Timer 确实有一种cancel方法可以防止后续执行。

因此,您应该尝试以下方法:

final Timer timer = new Timer();
// Note that timer has been declared final, to allow use in anon. class below
timer.schedule( new TimerTask()
{
    private int i = 10;
    public void run()
    {
        System.out.println("30 Seconds Later");
        if (--i < 1) timer.cancel(); // Count down ten times, then cancel
    }
}, 30000, 30000 //Note the second argument for repetition
);
于 2013-05-08T18:14:36.993 回答
0

我不知道这个解决方案是否有垃圾收集器的问题,但我还是把它扔在这里。也许有人清除了这一点,我也学到了一些东西。基本上,如果剩余时间,计时器会设置一个新计时器,并且应该在 5 分钟后停止。

主.java:

public class Main {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer(300000,30000);
        myTimer.startTimer();
    }
}

MyTimer.java:

import java.util.Timer;
import java.util.TimerTask;

public class MyTimer {
    private int totalRunningTime;
    private int currentTime = 0;
    private int intervalTime;

    private Timer timer = new Timer();

    public MyTimer(int totalRunningTime, int intervalTime) {
        this.totalRunningTime = totalRunningTime;
        this.intervalTime = intervalTime;
    }

    public void startTimer() {
        startTimer(intervalTime);
    }

    private void startTimer(int time) {
        timer.schedule(new TimerTask() {
            public void run() {

                if (currentTime <= totalRunningTime - intervalTime) {
                    printTimeSinceLast(intervalTime / 1000);
                    currentTime += intervalTime;
                    startTimer(intervalTime);
                } else if (currentTime < totalRunningTime) {
                    int newRestIntervalTime = totalRunningTime - currentTime;
                    printTimeSinceLast(newRestIntervalTime / 1000);
                    currentTime += newRestIntervalTime;
                    startTimer(newRestIntervalTime);
                }
            }
        }, time);
    }

    private void printTimeSinceLast(int timeSinceLast) {
        System.out.println(timeSinceLast + " seconds later.");
    }
}
于 2013-05-08T16:47:50.703 回答
0

这是我羞于提出的一种解决方法:

package test;

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

public class FiveMinutes {

    private static int count = 0;
    // main method just to add example
    public static void main(String[] args) {

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("Count is: " + count);
                if (count == 1) {
                    System.err.println("... quitting");
                    System.exit(0);
                }
                count++;
            }
        },
        // starting now
        new Date(),
        // 5 minutes
        300000l
        );  
    }
}

另请注意,应用程序可能不会运行5 分钟 - 请参阅 TimerTask 的文档

于 2013-05-08T16:22:16.393 回答
0

您的解决方案非常接近工作,您只需将延迟乘以计数器(在您的情况下,i):

public static void main(String[] args)
{
    for (int i = 1; i <= 10; i++) // start i at 1 for initial delay
    {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            public void run()
            {
                System.out.println("30 Seconds Later");
            }
        }, 30000 * i); // 5 second intervals
    }
}
于 2013-05-08T16:25:54.560 回答