代码之家  ›  专栏  ›  技术社区  ›  Lydon Ch

Java循环的持续时间

  •  11
  • Lydon Ch  · 技术社区  · 14 年前

    有没有一种方法可以让我在一定的时间内轻松地执行for循环?(不使用system.currentTimeMillis()自行测量时间)

    我想在Java中做这样的事情:

    int x = 0;
    for( 2 minutes )  {
       System.out.println(x++);
    }
    

    谢谢

    8 回复  |  直到 9 年前
        1
  •  24
  •   Peter Lang    9 年前

    不,没有内置的结构可以做到这一点。

    我想指出,您不应该使用System.CurrentTimeMillis()来执行或延迟指定时间段的任务。而是使用System.NanoTime()。前一种方法在Windows中不准确,后一种方法不考虑操作系统而准确。您可以使用TimeUnit枚举轻松地在以毫秒为单位的时间或任何其他时间单位与以纳秒为单位的时间之间切换。

    for (long stop=System.nanoTime()+TimeUnit.SECONDS.toNanos(2);stop>System.nanoTime();) {
      /*
       * Hammer the JVM with junk
       */
    }
    
        2
  •  10
  •   N3dst4    9 年前

    我想这就是你想要的:

    private final Thread thisThread = Thread.current();
    private final int timeToRun = 120000; // 2 minutes;
    
    new Thread(new Runnable() {
        public void run() {
            sleep(timeToRun);
            thisThread.interrupt();
        }
    }).start();
    
    while (!Thread.interrupted()) {
        // do something interesting.
    }
    

    这样可以避免重复执行系统调用以获取系统时钟值(这可能非常昂贵),并轮询当前线程的 interrupted 标记代替(更便宜)。

    编辑

    实际上没有 安全的 可选择轮询时钟或轮询标志。理论上,您可以修改上面的片段来调用 贬低 Thread.stop() 方法而不是 Thread.interrupt() .

    (我) 不是 推荐使用 线程停止() 和朋友们。它们有缺陷,使用起来很危险。我只是假装成 理论的 另一种选择。)

    编辑2

    只是为了指出使用 线程。中断() 具有设置共享标志的优点:

    • thread.interrupt()将导致某些阻塞I/O和同步方法取消阻塞并引发选中的异常。更新共享标志不会做到这一点。

    • 一些第三方库还检查中断标志,看看它们是否应该停止当前正在执行的操作。

    • 如果您的循环涉及到对其他方法等的调用,那么thread.interrupt()意味着您不必担心这些方法可以访问标志…如果他们需要的话。

    编辑3

    只是为了补充一下 sleep(N) 不能保证在 N 毫秒。但在正常情况下,它会相当接近。

        3
  •  3
  •   Endre Vestbø    13 年前

    我为这个问题做了一个简单但很糟糕的实现。我想避免计时器和时间任务,最终得到了这个快速修复解决方案。

    主要的想法是我只想创建一个独立的倒计时计时器,我可以启动它并调用isFinished()来检查倒计时是否完成。

    package RIPv3;
    
    /**
     * Creates a countdown timer which runs its own thread and uses CountdownTimerThread,                which runs yet another
     * thread.
     *
     * start() method is called to start the countdown.
     * isFinished() method is called to check if the countdown is finished or not.
     * 
     * ! Be Aware!
     * This is a quickfix and sucky implementation.
     * There will be a small delay. This is not accurate.
     * 
     * @author Endre Vestbø
     * @version 1.0 (09.05.2011)
     */
    public class CountdownTimer extends Thread {
    /* Countdown timer */
    private CountdownTimerThread timer;
    
    /**
     * Creates a new timer and sets time to count down
     * @param time
     *          Time to count down
     */
    public CountdownTimer(long time) {
        this.timer = new CountdownTimerThread(time);
    }
    
    public void run() {
        this.timer.start();
    }
    
    /**
     * @return
     *      False if timer is running, else true
     */
    public boolean isFinished() {
        if(this.timer.getState() == Thread.State.TERMINATED)
            return true;
    
        return false;
    }   
    }
    

     package RIPv3;
    
    /**
     * Used by CountdownTimer to count down time.
     * 
     * @author Endre Vestbø
     * @version 1.0  (09.05.2011)
     *
     */
    public class CountdownTimerThread extends Thread {
    private long time;
    
    /** Create a new timer */
    public CountdownTimerThread(long time) {
        this.time = time;
    }
    
    /**
     * Start a countdown
     * @param period
     *      Period to count down given in milliseconds
     */
    public void run() {
        try {
            sleep(this.time);
        } catch (InterruptedException e) {
    
        }
    }
    }
    
        4
  •  1
  •   matsev    14 年前

    下面是另一个建议:

    public class TimerLoop {
        private final AtomicBoolean loop = new AtomicBoolean();

    public void run(Runnable runnable, long duration, TimeUnit timeUnit) {
        loop.set(true);
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                loop.set(false);
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, timeUnit.toMillis(duration));
        while (loop.get()) {
            runnable.run();
        }
    }
    

    }

    方法执行 run() 提供的方法 Runnable 重复直到计时器过期。

    考虑事项:

    • 时间大概是。
    • 注意如何实现 () 方法,因为它可能会消耗您所有的CPU电源。
    • 除非创建的新实例 TimerLoop 为每个类 可运行的 你想执行的。
        5
  •  1
  •   Joe Phillips    14 年前

    不。考虑到简单地编写一个使用System.CurrentTimeMillis()的函数(或您选择的任何时间函数)有多简单,这是一种奇怪的请求。更多的情况可能是有序的。

        6
  •  0
  •   MaxGuernseyIII    14 年前

    我不认为有一种方法可以循环一段时间而不检查是否循环了一段时间。

        7
  •  0
  •   Jim Ferrans    14 年前

    根据您的用例,类中的两个sleep()方法之一 Thread 可以 符合要求,但听起来你必须对System.CurrentTimeMillis()大惊小怪,这看起来很奇怪。

    Thread thread = Thread.currentThread();
    thread.sleep(10);      // 10 milliseconds
    thread.sleep(12, 345); // 12 milliseconds and 345 nanoseconds.
    
        8
  •  0
  •   Vaishak Suresh    14 年前

    循环在值比较上迭代,而不是在持续时间内迭代。因此,如果没有自己分配和比较系统时间,就无法完成。 如果您希望它是直观的,那么您可以有一个内部使用毫秒的函数,但需要几分钟作为参数并使用它。

    不,不能在其中使用线程或sleep方法,因为这不能确保准确的时间。如果在给定的时间过后,处理器正忙于处理其他线程,那么线程将继续等待。