延迟执行 Java 方法中的代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28147557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:04:40  来源:igfitidea点击:

Delay execution of code in method Java

javaandroiddelayjdk1.6

提问by Confuse

I want to generate random number after every 2 seconds in my java (Android) program continuously for at least 10 minutes. But I just want to pause/delay execution of code in only one method and not the whole program.

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

I tried using Thread like this -

我尝试像这样使用线程 -

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

However, this doesn't work as Thread.sleepstop the whole program execution instead on just stopping execution of code inside method and my whole screen becomes blank.

但是,这并不能Thread.sleep停止整个程序的执行,而只是停止执行方法内部的代码,我的整个屏幕变为空白。

I also tried using Handlerbut it didn't work either as it doesn't stop execution of code in my method and instead just stack up.

我也尝试使用,Handler但它也没有工作,因为它不会停止在我的方法中执行代码,而只是堆叠起来。

This will demonstrate the working of it better -

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

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
}

So the code stacks up making it equivalent to using while loop and make it incredibly slow.

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

Also, since I'm developing app for Android, I'm running on Java SE 6, so I can't use scheduleAtFixedRate. Is there any other way in which I can accomplish this?

另外,由于我正在为 Android 开发应用程序,我在 Java SE 6 上运行,所以我不能使用scheduleAtFixedRate. 有没有其他方法可以做到这一点?

Thanks a lot!

非常感谢!

采纳答案by kamituel

Option 1:Using threads, you might run your job off the main (UI) thread:

选项 1:使用线程,您可以在主 (UI) 线程之外运行您的工作:

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

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

Then, if this new thread you'd like to modify UI (i.e. show/hide button, display something on the screen etc), remember to pass that through the UI thread, as only this one can modify the UI. You might consider using Activity.runOnUiThread()for that.

然后,如果您想修改这个新线程(即显示/隐藏按钮、在屏幕上显示某些内容等),请记住通过 UI 线程传递它,因为只有这个线程可以修改 UI。您可能会考虑为此使用Activity.runOnUiThread()

Option 2:Another, more Android-style way of approaching that issue is to use AsyncTask. It contains three callbacks which can be used to do work on- and off- the UI thread. Sketch of such a code could look like:

选项 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.
   }
 }

Option 3:Then there is also a Timer, as suggested by @Stultuske. It's less flexible then AsyncTask, but handles the interval for you.

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

回答by Anthone

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);
    }

and when you want to stop it

当你想阻止它时

timer.cancel()

回答by FrancescoC

Depending on your needs, you can still accomplish what you seek with Handler.

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

You don't have to create/start the Handler in a while loop(which, as you noticed, just stacks up unless you stop the loop itself, but it is a nonsense).

您不必在 while 循环中创建/启动处理程序(正如您所注意到的,除非您停止循环本身,否则它只会堆积起来,但这是无稽之谈)。

Just create the Handler and tell him to post delayed your Runnable instance. In the Runnable at the very end you check your conditions. If it is still OK, then post another runnable delayed, else you do nothing and the Handler will have no more executions.

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

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

The only downside is that Handler could freeze if the device is not used for a while, meaning it will start the counting back from where it left once the device screen is turned on.

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

It could do like 1 minute of correct work, then block at 1.4 seconds when the device is gone in sleep mode, and once it is turned on again, Handler would do the remaining 0.6 seconds.

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

Still, not knowing your needs you may be unaffected by this behavior and the answer may fit you.

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

回答by Randyka Yudhistira

if you want to use thread, do it like this :

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

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