import java.util.LinkedList;
import java.util.Queue;
-import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import android.os.SystemClock;
/*
* Copyright © 2013 Marius Gavrilescu
*/
abstract class ExecutableRunnable implements Runnable {
/** Executor used to execute instances of this class */
- private static final Executor executor = Executors.newSingleThreadExecutor();
+ private static final ScheduledExecutorService EXECUTORS = Executors.newSingleThreadScheduledExecutor();
/** Queue containing <code>ExecutableRunnable</code>s that should be retried */
- private static final Queue<ExecutableRunnable> retryPendingTasks = new LinkedList<ExecutableRunnable>();
+ private static final Queue<ExecutableRunnable> RETRY_PENDING_TASKS = new LinkedList<ExecutableRunnable>();
+ /** Minimum interval between task retries, in milliseconds */
+ private static final long RETRY_INTERVAL = 30000;
+ /** {@link SystemClock#elapsedRealtime()} time of last successful call to {@link #retryTasks()} */
+ private static long lastRetry = 0;
+ /** True if a retryTasks run is already scheduled on {@link #EXECUTORS} */
+ private static volatile boolean retryIsScheduled = false;
/** Run all tasks that should be retried */
public static final void retryTasks(){
- synchronized(retryPendingTasks){
- for(ExecutableRunnable task : retryPendingTasks)
- task.execute();
- retryPendingTasks.clear();
+ if(!retryIsScheduled && lastRetry+RETRY_INTERVAL>SystemClock.elapsedRealtime()){
+ retryIsScheduled = true;
+ EXECUTORS.schedule(new Runnable() {
+ @Override
+ public void run() {
+ retryTasks();
+ retryIsScheduled = false;
+ }
+ }, RETRY_INTERVAL, TimeUnit.MILLISECONDS);
+ return;
+ }
+ synchronized(RETRY_PENDING_TASKS){
+ for(ExecutableRunnable task : RETRY_PENDING_TASKS)
+ EXECUTORS.execute(task);
+ RETRY_PENDING_TASKS.clear();
}
+ lastRetry=SystemClock.elapsedRealtime();
}
/** Execute this <code>ExecutableRunnable</code> */
public final void execute(){
retryTasks();
- executor.execute(this);
+ EXECUTORS.execute(this);
}
/** Mark this <code>ExecutableRunnable</code> as needing to be retried later */
protected final void retry(){
- synchronized(retryPendingTasks){
- retryPendingTasks.add(this);
+ synchronized(RETRY_PENDING_TASKS){
+ RETRY_PENDING_TASKS.add(this);
}
}
}