8

ScheduledExecutorServiceが次に起動する時刻の現在のミリ秒またはその他の時間測定値を決定する方法はありますか?

scheduleTaskExecutorUpdate = Executors.newSingleThreadScheduledExecutor();

実行時間が長く、実行ScheduledExecutorService(A)時間が短いScheduledExecutorService(B)場合は、TextViewを更新して、次に起動するタイミングのカウントダウンを表示したいと思いScheduledExecutorService(A)ます。

4

1 に答える 1

9

ScheduledFutureエグゼキュータでスケジュールされたすべてのタスクのを追跡する場合は、はい。これは、次のタスクが実行されるまでの最小遅延を決定する問題になります。これは、かなり信頼できる見積もりであるはずです。

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

...または、1つのタスクについて、次のことを行うだけです。

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

さて、あなたがそれをたくさんするつもりなら、複数のタスクで、私はあなたがを維持することをお勧めしますDelayQueueScheduledFutureただし、定期的なタスクによって引き起こされる変更を維持せずに、単にsをキューにスローすることはできません。幸いなことに、クラスはそのメソッド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);
于 2012-08-31T21:14:00.863 に答える