2012-08-31 23 views
6

पर आग लग जाएगी, क्या मौजूदा मिलीसेकंद या अन्य समय माप निर्धारित करने का कोई तरीका है जब शेड्यूल किए गए एक्सेलसर्स सेवा अगली बार जा रही है?निर्धारित करें कि एक निर्धारित अनुसूचित जाति सेवा अगले

scheduleTaskExecutorUpdate = Executors.newSingleThreadScheduledExecutor(); 

मैं एक लंबे समय तक ScheduledExecutorService(A) चल रहा है और एक छोटी चल ScheduledExecutorService(B) से मैं एक TextView अद्यतन करने के लिए, जब ScheduledExecutorService(A) अगले आग करने जा रहा है की उल्टी गिनती का प्रदर्शन करना चाहते हैं।

उत्तर

8

यदि आप निष्पादक के साथ निर्धारित सभी कार्यों के लिए 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); 
+0

+1 अच्छा समाधान! – RNJ

+0

@ आरएनजे उम्मीद है कि यह अब भी एक बेहतर समाधान है! – oldrinb

संबंधित मुद्दे