一段时间内运行代码的更好方法


问题内容

我需要在预定义的时间长度内运行一些代码,当时间到时它需要停止。当前,我正在使用TimerTask来允许代码执行一段设定的时间,但这导致代码创建无尽的线程,并且效率很低。有更好的选择吗?

当前代码;

// Calculate the new lines to draw 
            Timer timer3 = new Timer();
            timer3.schedule(new TimerTask(){
                public void run(){
                    ArrayList<String> Coords = new ArrayList<String>();
                    int x = Float.valueOf(lastFour[0]).intValue();
                    int y = Float.valueOf(lastFour[1]).intValue();
                    int x1 = Float.valueOf(lastFour[2]).intValue();
                    int y1 = Float.valueOf(lastFour[3]).intValue();
                    //Could be the wrong way round (x1,y1,x,y)?
                    Coords = CoordFiller.coordFillCalc(x, y, x1, y1);
                    String newCoOrds = "";
                    for (int j = 0; j < Coords.size(); j++)
                    {
                        newCoOrds += Coords.get(j) + " ";
                    }
                    newCoOrds.trim();
                    ClientStorage.storeAmmendedMotion(newCoOrds);

                }

            }
            ,time);

问题答案:

如果您使用的是Java5或更高版本,请考虑ScheduledThreadPoolExecutorFuture。使用前者,您可以安排任务在指定的延迟后或以指定的时间间隔运行,因此,它可以Timer更可靠地接管的角色。

Timer设施管理延迟(“每100毫秒运行一次此任务”)和定期(“每10毫秒运行此任务”)任务的执行。但是,它Timer有一些缺点,ScheduledThreadPoolExecutor应将其视为替代品。[…]

A
Timer仅创建一个用于执行计时器任务的线程。如果计时器任务花费的时间太长,则其他计时器的计时精度TimerTask可能会受到影响。如果TimerTask安排一个重复执行周期为每10毫秒运行一次,而另一个TimerTask重复运行则需要40毫秒运行,则长时间运行的任务完成后,重复执行的任务(取决于是以固定速率还是固定延迟计划)将被快速连续调用四次。
,或完全“缺失”四个调用。计划线程池通过允许您提供多个线程来执行延迟和定期任务来解决此限制。

另一个问题Timer是,如果TimerTask抛出未经检查的异常,它的行为就会很差。该Timer线程不会捕获该异常,因此从a引发的未经检查的异常将TimerTask终止计时器线程。Timer在这种情况下也不会恢复线程;而是错误地认为整个都Timer被取消了。在这种情况下,TimerTask已调度但尚未执行的永远不会运行,并且无法调度新任务。

摘自Java Concurrency inPractice第6.2.5节。

Future小号可以限制运行最多在指定的时间(扔TimeoutException如果不能按时完成)。

更新资料

如果您不喜欢上述内容,则可以使任务衡量其自身的执行时间,如下所示:

int totalTime = 50000; // in nanoseconds
long startTime = System.getNanoTime();
boolean toFinish = false;

while (!toFinish) 
{
    System.out.println("Task!");
    ...
    toFinish = (System.getNanoTime() - startTime >= totalTime);
}