2012-08-31 7 views
6

ScheduledExecutorServiceが次に発生する予定の現在のミリ秒またはその他の時間を判断する方法はありますか?ScheduledExecutorServiceが次に発生するタイミングを決定する

scheduleTaskExecutorUpdate = Executors.newSingleThreadScheduledExecutor(); 

私は長いScheduledExecutorService(A)を実行しているし、短いランニングScheduledExecutorService(B)から私はScheduledExecutorService(A)は、次の発射しようとしたときのカウントダウンを表示する、のTextViewを更新したいと思います。

答えて

8

executorでスケジュールされたすべてのタスクについてScheduledFutureを追跡している場合は、yesを指定します。これは、次のタスクが発射されなければならないまでの最小遅延を決定する問題となり、これはかなり信頼できる推定値でなければならない。

final Collection<ScheduledFuture<?>> futures = ...; 
/* for each schedule, add it to the above collection */ 
... 
final long delay = Collections.min(futures).getDelay(TimeUnit.MILLISECONDS); 

...または、一つのタスクのために、あなたは単に実行します。

final ScheduledFuture<?> future = ...; 
final long delay = future.getDelay(TimeUnit.MILLISECONDS); 

さて、あなたはみとめタスクで、たくさんそれをやっているつもりなら、私は思いますDelayQueueを維持することをお勧めします。ただし、定期的なタスクによる変更を維持することなく、単にキューにScheduledFutureを投げることはできません。幸運にも、クラスScheduledThreadPoolExecutorは、decorateTaskの方法でこれをうまく処理する必要があります。

これは、独自のScheduledThreadPoolExecutorを直接作成する必要があることに注意してください。以下のようなものが動作するかもしれません。

public class TrackingSingleThreadScheduledExecutor 
    extends ScheduledThreadPoolExecutor { 

    private final DelayQueue<ScheduledFuture<?>> tasks 
     = new DelayQueue<RunnableScheduledFuture<?>>(); 

    public TrackingSingleThreadScheduledExecutor() { 
    super(1); 
    } 

    public DelayQueue<? extends ScheduledFuture<V>> tasks() { 
    return tasks; 
    } 

    public ScheduledFuture<V> next() { 
    return tasks.peek(); 
    } 

    protected <V> RunnableScheduledFuture<V> decorateTask 
     (final Callable<V> callable, final RunnableScheduledFuture<V> task) { 
    return new QueueAwareTask(task); 
    } 

    protected <V> RunnableScheduledFuture<V> decorateTask 
     (final Runnable runnable, final RunnableScheduledFuture<V> task) { 
    return new QueueAwareTask(task); 
    } 

    private final class QueueAwareTask<V> implements RunnableScheduledFuture<V> { 

    private final RunnableScheduledFuture<V> inner; 

    public QueueAwareTask(final RunnableScheduledFuture<V> inner) { 
     this.inner = inner; 
    } 

    public boolean isPeriodic() { 
     return inner.isPeriodic(); 
    } 

    public long getDelay(final TimeUnit unit) { 
     return inner.getDelay(unit); 
    } 

    public void run() { 
     inner.run(); 
     if (queue.remove(inner) && inner.isPeriodic() 
      && !inner.isCancelled()) { 
     queue.add(inner); 
     } 
    } 

    public int compareTo(final Delayed other) { 
     return inner.compareTo(other); 
    } 

    public boolean cancel(final boolean mayInterruptIfRunning) { 
     final boolean cancelled = inner.cancel(mayInterruptIfRunning); 
     if (cancelled) { 
     queue.remove(inner); 
     } 
     return cancelled; 
    } 

    public boolean isCancelled() { 
     return inner.isCancelled(); 
    } 

    public boolean isDone() { 
     return inner.isDone(); 
    } 

    public V get() throws InterruptedException, ExecutionException { 
     return inner.get(); 
    } 

    public V get(final long timeout, final TimeUnit unit) 
     throws InterruptedException, ExecutionException { 
     return inner.get(timeout, unit); 
    } 
    } 
} 

次に使用方法は次のとおりです。

final TrackingSingleThreadScheduledExecutor executor 
    = new TrackingSingleThreadScheduledExecutor(); 
... 
final long delay = executor.next().getDelay(TimeUnit.MILLISECONDS); 
+0

+1良い解決策! – RNJ

+0

@RNJうまくいけば、それは今より良いソリューションです! – oldrinb

関連する問題