在方法Java中延迟执行代码

时间:2015-01-26 09:33:02

标签: java android delay jdk1.6

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

我尝试使用像这样的线程 -

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。还有其他方法可以实现这个目标吗?

非常感谢!

4 个答案:

答案 0 :(得分:6)

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()

答案 1 :(得分:5)

选项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(即显示/隐藏按钮,在屏幕上显示某些东西等),记得通过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灵活,但为你处理间隔。

答案 2 :(得分:5)

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

你不必在while循环中创建/启动Handler(正如你所注意到的那样,除非你自己停止循环,否则只是堆叠起来,但这是无意义的。)

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

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秒。

但是,不知道您的需求,您可能不受此行为的影响,而答案可能适合您。

答案 3 :(得分:3)

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

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