यदि आप निष्पादक के साथ निर्धारित सभी कार्यों के लिए ScheduledFuture
एस का ट्रैक रखते हैं, तो हाँ। यह तब तक न्यूनतम देरी निर्धारित करने की समस्या बन जाता है जब तक कि अगले कार्य को आग लगाना न पड़े, जो कि काफी विश्वसनीय अनुमान होना चाहिए।
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);
+1 अच्छा समाधान! – RNJ
@ आरएनजे उम्मीद है कि यह अब भी एक बेहतर समाधान है! – oldrinb