A better way to run code for a period of time

前端 未结 4 638
遥遥无期
遥遥无期 2020-12-13 22:50

I need to run some code for a predefined length of time, when the time is up it needs to stop. Currently I am using a TimerTask to allow the code to execute for a set amount

4条回答
  •  伪装坚强ぢ
    2020-12-13 23:11

    If you are using Java5 or later, consider ScheduledThreadPoolExecutor and Future. With the former, you can schedule tasks to be run after a specified delay, or at specified intervals, thus it takes over the role of Timer, just more reliably.

    The Timer facility manages the execution of deferred ("run this task in 100 ms") and periodic ("run this task every 10 ms") tasks. However, Timer has some drawbacks, and ScheduledThreadPoolExecutor should be thought of as its replacement. [...]

    A Timer creates only a single thread for executing timer tasks. If a timer task takes too long to run, the timing accuracy of other TimerTasks can suffer. If a recurring TimerTask is scheduled to run every 10 ms and another TimerTask takes 40 ms to run, the recurring task either (depending on whether it was scheduled at fixed rate or fixed delay) gets called four times in rapid succession after the long-running task completes, or "misses" four invocations completely. Scheduled thread pools address this limitation by letting you provide multiple threads for executing deferred and periodic tasks.

    Another problem with Timer is that it behaves poorly if a TimerTask throws an unchecked exception. The Timer thread doesn't catch the exception, so an unchecked exception thrown from a TimerTask terminates the timer thread. Timer also doesn't resurrect the thread in this situation; instead, it erroneously assumes the entire Timer was cancelled. In this case, TimerTasks that are already scheduled but not yet executed are never run, and new tasks cannot be scheduled.

    From Java Concurrency in Practice, section 6.2.5.

    And Futures can be constrained to run at most for the specified time (throwing a TimeoutException if it could not finish in time).

    Update

    If you don't like the above, you can make the task measure its own execution time, as below:

    int totalTime = 50000; // in nanoseconds
    long startTime = System.getNanoTime();
    boolean toFinish = false;
    
    while (!toFinish) 
    {
        System.out.println("Task!");
        ...
        toFinish = (System.getNanoTime() - startTime >= totalTime);
    }
    

提交回复
热议问题