【问题标题】:How to schedule a random timing (every random minutes) event如何安排随机定时(每随机分钟)事件
【发布时间】:2017-06-07 16:18:18
【问题描述】:

我正在开发一个 Android 应用程序,我正在尝试管理一个振动事件。 我需要在检查开关时每隔几分钟安排一次。我一直在使用这个代码:

int delay3 = (60 + new Random().nextInt(60)) * 1000;

timer3.schedule(timerTask3, 0, delay3);

但计时器不会改变delay3,直到取消选中并再次检查开关。有没有办法在随机时间安排事件,即delay3 应该在每次任务运行时更改而不取消选中开关?

谢谢。

【问题讨论】:

  • 分享你写的代码

标签: java android random timer timertask


【解决方案1】:

安排任务在随机延迟后运行一次。在任务内部,在所需进程之后,随机延迟后重新调度它。

例子:

Random random = new Random();
Timer timer = new Timer();
timer.schedule(new MyTimerTask(timer, random), random.nextInt(10000));

与:

private static class MyTimerTask extends TimerTask {
    private final Timer timer;
    private final Random random;

    public MyTimerTask(Timer timer, Random random) {
        this.timer = timer;
        this.random = random;
    }

    @Override
    public void run() {
        System.out.println("TEST");
        timer.schedule(new MyTimerTask(timer, random), random.nextInt(10000));
    }
}

【讨论】:

  • 谢谢。它运作良好。你能帮我取消任务吗?
  • 这种方式有个缺点,如果一个任务失败了,后面的任务就不会被调度了
  • @yusong 如果这是您想要的行为,您可以将重新调度放在运行方法的顶部。但是您需要添加任务所需时间的最小值,以避免同时运行多个任务实例。
  • @italianfranny (抱歉这么晚了)您可以使用一个 AtomicBoolean 给任务,并且您的主线程稍后会更改,具体取决于它的值是否在 run() 方法中重新安排。我认为您还需要在任务中存储 AtomicBoolean 的字段是“易失的”以确保它工作(因为该值将被另一个线程更改而不是读取它的线程)。
  • 嗨 Nyamiou,我认为解决这个问题的好方法是总是在 finally 块中安排下一个任务,然后即使任务失败,finally 块仍然会被执行
【解决方案2】:

您也可以使用android.os.Handler 类的postDelayed 方法代替 java.util.Timer 类的scheduleAtFixedRate 方法。

只需创建android.os.Handler 类的实例并调用android.os.Handler 实例的postDelayed 方法,而不是创建java.util.Timer 类的实例并调用java.util.Timer 实例的scheduleAtFixedRate 方法。

请注意,您必须将TimerTask 接口替换为Runnable 接口。

Runnable 实例的run 方法结束时(作为第一个参数传递给android.os.Handler 实例的postDelayed 方法)以新的随机延迟再次调用相同的postDelayed 方法android.os.Handler 实例与相同 Runnable 实例!

无需创建TimerTask 的新实例,也无需创建Runnable 的新实例!

这更有效,因为在堆内存上分配的对象更少,因此垃圾收集器在以这种方式从堆内存中释放对象时不那么忙!

有一个我自己用自己的想法写的demo:

import android.os.Handler;
import java.util.Random;

public class Demo
{
   private boolean postAgain;
   public void start()
   {
       postAgain = true;
       final Handler handler = new Handler();
       final Random random = new Random();
       final Runnable runnable = () ->
       { 
           log.d("Hello");
           if (postAgain)
           {
               handler.postDelayed(runnable,random.nextInt(10000));
           }
       };
       handler.postDelayed(runnable,random.nextInt(10000));
   }

   public void stop() { postAgain = false; }

请注意,上面的代码使用了 Java 8 lambda 表达式。 在 Java 7 及更低版本中,您可以创建实现 run 方法的 Runnable 接口的实例,而无需定义实现的新命名类 Runnable 接口。

另请注意,start 方法的所有局部变量必须全部为 final,以便能够在 lambda 表达式或 Runnable 实例的 run 方法中使用它们。

调用start 方法以随机延迟重复打印“Hello”并调用stop 方法来停止此操作。

请注意,stop 方法仅将 boolean 字段从 true 设置为 false 以停止循环。

【讨论】:

    猜你喜欢
    • 2020-01-10
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 2014-09-08
    相关资源
    最近更新 更多