Skip to content Skip to sidebar Skip to footer

Lock A Runnable Until Finished

I'm using Runnable as a loop in Android. As this: Timer timer = new Timer(); timer.schedule(new looper(m_mainView, this),0, Rate); Which runs every 'Rate' milliseconds. Th

Solution 1:

The looper object is solely owned by the timer.schedule so no-one can call that object's run method except the timer.schedule. If the run method takes longer that the period you have specified then it is likely that the run method will be called again before it completes - especially since you have passed off the actual running of the the task to the UI thread.

You have two simple alternatives:

  1. Set a flag in your run method indicating that you are running and make run do nothing if it is set.
  2. Fire off the timer after a fixed delay only, not with a repeat time. At the end of your run, fire it off again.

For 1:

classLooperextendsTimerTask {
  // ** Add this **volatilebooleanrunning=false;

  publicLooper() {
  }

  @Overridepublicvoidrun() {
    // ** Add this **if (!running) {
      running = true;
      try {
        runOnUiThread(newRunnable() {
          @Overridepublicvoidrun() {
          }

        });
        // ** Add this **
      } finally {
        running = false;
      }

    }
  }

}

Second method:

timer.schedule(newlooper(m_mainView, this, Rate),newDate());
...
classLooperextendsTimerTask {
  finallong rate;
  final Looper looper;

  publicLooper(long rate) {
    this.rate = rate;
    looper = this;
    // ...
  }

  @Overridepublicvoidrun() {
    runOnUiThread(newRunnable() {
      @Overridepublicvoidrun() {
        // ...newTimer().schedule(looper, newDate(newDate().getTime() + rate));
      }

    });

  }

}

Solution 2:

You should add synchronized to the method declaration like this:

publicsynchronizedvoidrun()

Solution 3:

First of all, why is there any risk that the run method will be called again? If that's true it sounds like a design deficiency to me. Second, instead of TimerTask, you might be better off using a ScheduledExecutorService instead. That's the standard, simplest and safest way of executing scheduled tasks at a fixed interval. Your user code won't be accessible from anything but the executor service and you can get a ScheduledFuture from it to get a return value so that you know when the task is done (the ScheduledFuture blocks when you call get()). Take a look at Java Concurrency in Practice for more...

Post a Comment for "Lock A Runnable Until Finished"