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

我需要在预定义的时间内运行一些代码,当时间到了需要停止时。 目前我正在使用TimerTask来允许代码执行一段时间,但这会导致代码创建无穷无尽的线程,而这只是效率不高。 还有更好的选择吗?

当前代码;

// Calculate the new lines to draw Timer timer3 = new Timer(); timer3.schedule(new TimerTask(){ public void run(){ ArrayList Coords = new ArrayList(); 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视为其替代品。 […]

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

Timer另一个问题是,如果TimerTask抛出未经检查的exception,它的行为很差。 Timer线程没有捕获exception,因此从TimerTask抛出的未经检查的exception终止了定时器线程。 在这种情况下, Timer也不会恢复线程; 相反,它错误地假设整个Timer被取消了。 在这种情况下,已经调度但尚未执行的TimerTask永远不会运行,并且无法安排新任务。

从Java Concurrency in Practice ,第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); } 

[…]目前我正在使用TimerTask来允许代码执行一段时间[…]

计时器任务永远不会停止当前正在运行的任务。 实际上,它的唯一目的是一遍又一遍地重启任务。

没有与执行任务的紧密合作,没有简单的方法来解决这个问题。 最好的方法是让任务监视它自己的执行,并确保它在时间结束时返回(终止)。

如果通过停止意味着程序必须退出,解决方案是为您的处理创建一个线程并将其标记为守护进程,启动它并在主线程中hibernate所需的时间,然后只需从main()方法返回。

抓住,如果停止,你的意思是停止处理。

还应该注意,通常你只需要创建一个Timer()。 从代码片段我猜你正在创建多个Timer()对象。

计划方法中的时间是运行时间,而不是运行时间。

如果超出时间限制,请考虑在for循环之前设置一个开始时间并在for循环中放置一个中断。

 long startedAt = System.currentTimeMillis(); long finishedCorrectly = true; for (int j = 0; j < Coords.size(); j++) { newCoOrds += Coords.get(j) + " "; if ((System.currentTimeMillis() - startedAt) > MAX_TIME_TO_RUN) { finishedCorrectly = false; break; } }