延迟执行方法 Java 中的代码

Delay execution of code in method Java

我想在我的 java (Android) 程序中每 2 秒生成一个随机数,持续至少 10 分钟。但我只想 pause/delay 只在一个方法中执行代码,而不是整个程序。

我试过像这样使用 Thread -

boolean stop = false;
int random_number = 0;

while(true){
    if(stop){  //if stop becomes true, then
        return;  //terminate the method
    }

    random_number = Math.random(); //generate random number
                                   //which is used bu some other
                                   //part of code
    try {
        Thread.sleep(2000);        //delay the code for 2 secs
    } catch(InterruptedException ex) {  //and handle the exceptions
        Thread.currentThread().interrupt();
    }
}

然而,这不起作用,因为 Thread.sleep 停止整个程序的执行,而不是仅仅停止方法内部代码的执行,我的整个屏幕变成空白。

我也尝试过使用 Handler 但它也没有用,因为它不会停止我方法中代码的执行,而是只是叠加。

这将更好地展示它的工作原理 -

while(true){
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            System.out.println("After 2 secs"); //this gets printed
                                               //later
        }
    }, 2000);
    System.out.println("Before 2 secs"); //this gets printed first
}

所以代码堆积起来,相当于使用 while 循环,并且速度非常慢。

此外,由于我正在为 Android 开发应用程序,我在 Java SE 6 上 运行,所以我无法使用 scheduleAtFixedRate。还有其他方法可以实现吗?

非常感谢!

如果你想使用线程,这样做:

Thread t = new Thread(){
    public void run(){
      while(true){
         if(stop) break;
         random_number = Math.random();
         sleep(2000);
      }
    }
};
t.start();

选项 1: 使用线程,您可能 运行 您的工作脱离主 (UI) 线程:

new Thread(new Runnable() {
  // some code here ...

  // This might be in a loop.
  try {
    Thread.sleep(2000);
  } catch(InterruptedException ex) {
    // Handle ...
  }
 }
}).start();

然后,如果你想修改这个新线程 UI(即 show/hide 按钮,在屏幕上显示一些东西等),请记住将其传递给 UI线程,因为只有这个可以修改 UI。您可以考虑为此使用 Activity.runOnUiThread()

选项 2: 另一种更接近 Android 风格的方法是使用 AsyncTask。它包含三个回调,可用于在 UI 线程上和关闭时进行工作。此类代码的草图可能如下所示:

 private class MyTask extends AsyncTask<Void, Void, Void> {
   protected Void doInBackground(Void... param) {
     // This method is running off the UI thread.
     // Safe to stop execution here.

     return null;
   }

   protected void onProgressUpdate(Void... progress) {
     // This methid is running on the UI thread. 
     // Do not stop thread here, but safe to modify the UI.
   }

   protected void onPostExecute(Long result) {
     // Also on UI thread, executed once doInBackground()
     // finishes.
   }
 }

选项 3: 然后还有一个 Timer,正如@Stultuske 所建议的。它不如 AsyncTask 灵活,但会为您处理间隔。

private Timer timer;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                //Generate number
            }
        }, 2000, 2000);

//Documentation (From SDK)
/**
             * Schedule a task for repeated fixed-rate execution after a specific delay
             * has passed.
             *
             * @param task
             *            the task to schedule.
             * @param delay
             *            amount of time in milliseconds before first execution.
             * @param period
             *            amount of time in milliseconds between subsequent    executions.
    public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
                if (delay < 0 || period <= 0) {
                    throw new IllegalArgumentException();
                }
                scheduleImpl(task, delay, period, true);
    }

以及当你想停止它时

timer.cancel()

根据您的需要,您仍然可以使用 Handler 完成您想要的。

您不必在 while 循环中 create/start Handler(如您所见,除非您停止循环本身,否则它只会堆积起来,但这是无稽之谈)。

只需创建 Handler 并告诉他 post 延迟您的 Runnable 实例。在最后的 Runnable 中,您检查您的条件。如果它仍然正常,那么 post 另一个可运行的延迟,否则你什么都不做,处理程序将不再执行。

final Handler handler = new Handler();
Runnable runnable = new Runnable() {

    @Override
    public void run() {
        System.out.println("After 2 secs");
        random_number = Math.random();

        if (!stop) // should not be stopped, so we add another runnable;
        {
          handler.postDelayed(this, 2000);
        }
   }

handler.postDelayed(runnable, 2000);

唯一的缺点是,如果设备一段时间不使用,Handler 可能会死机,这意味着一旦设备屏幕打开,它就会从离开的地方开始倒计时。

它可以做 1 分钟的正确工作,然后当设备进入睡眠模式时在 1.4 秒时阻塞,一旦再次打开,Handler 将完成剩余的 0.6 秒。

不过,在不了解您的需求的情况下,您可能不会受到此行为的影响,而且答案可能适合您。