2009-10-05 10 views
12

Załóżmy, że mam zadanie, które pobiera elementy z java.util.concurrent.BlockingQueue i przetwarza je.ScheduledEexecutorService ze zmiennym opóźnieniem

public void scheduleTask(int delay, TimeUnit timeUnit) 
{ 
    scheduledExecutorService.scheduleWithFixedDelay(new Task(queue), 0, delay, timeUnit); 
} 

Jak mogę zaplanować/zmienić harmonogram zadania, jeśli częstotliwość może być zmieniana dynamicznie?

  • Chodzi o to, aby wziąć strumień aktualizacji danych i propagować je w partii do GUI
  • Użytkownik powinien być w stanie zmieniać częstotliwość aktualizacji
+0

Nie jest dla mnie jasne, dlaczego używasz kolejki blokującej. jeśli kolejka youe jest pusta. Zakładam, że zaplanowane zadanie zostanie zablokowane. czy to twoja intencja? Prawdopodobnie spowoduje to zamieszanie w harmonogramie zadań. –

+0

Wybrałem implementację ArrayBlockingQueue, ponieważ musi ona być bezpieczna dla wątków, przestrzegać kolejności FIFO i być ograniczona. Nawet jeśli zadanie blokuje, to nie powinno mylić planowania zadań, czy nie? – parkr

+0

Używasz poprawnej implementacji BlockingQueue (w rzeczywistości ScheduledThreadPoolExecutor używa jej wewnętrznie). Dlaczego jednak rozpowszechniasz swoje aktualizacje GUI, używając w ogóle timera? Dlaczego nie zrobić tego w czasie rzeczywistym? Czy jest zbyt wiele aktualizacji? Czy martwisz się obracaniem nici Swing? – Adamski

Odpowiedz

6

Nie sądzę, aby można było zmienić oprocentowanie na stałą stopę procentową. Myślę, że musisz użyć schedule(), aby wykonać jednorazowe zdjęcie, i zaplanować ponownie, gdy zostanie ukończone (ze zmodyfikowanym czasem oczekiwania, jeśli jest to wymagane).

+1

Dzięki - Zrobiłem "opóźnienie" zmiennej instancji i dodałem prywatną metodę, aby wykonać następujące czynności: while (! ExecutorService.isShutdown) {executorService.schedule (nowe zadanie (kolejka), opóźnienie, TimeUnit.MILLISECONDS); } – parkr

1

nie należy używać scheduleAtFixedRate, jeśli próbujesz przetworzyć kilka zadań kolejkowania z określoną częstotliwością? scheduleWithFixedDelay będzie tylko czekać na określone opóźnienie, a następnie wykonać jedno zadanie z kolejki.

W obu przypadkach metody schedule* w obiekcie ScheduledExecutorService zwrócą numer referencyjny ScheduledFuture. Jeśli chcesz zmienić stawkę, możesz anulować ScheduledFuture i zmienić harmonogram zadania z inną stawką.

+0

scheduleWithFixedDelay (...) - Tworzy i wykonuje okresową akcję, która zostaje aktywowana po pierwszym określonym opóźnieniu początkowym, a następnie z określonym opóźnieniem między zakończeniem jednego wykonania i rozpoczęciem następnego. Jeśli jakakolwiek realizacja zadania napotka wyjątek, kolejne egzekucje zostaną wyłączone. W przeciwnym razie zadanie zakończy się tylko przez anulowanie lub zakończenie executora. – parkr

+0

Czy możesz podać przykład kodu anulowania i zmiany harmonogramu? A co z aktualizacjami w toku? – parkr

0

scheduleWithFixedDelay (...) zwraca RunnableScheduledFuture. Aby zmienić harmonogram, możesz po prostu anulować i zmienić harmonogram. Przełożyć go, może po prostu owinąć dowcip RunnableScheduledFuture nowy Runnable:

new Runnable() { 
    public void run() { 
     ((RunnableScheduledFuture)future).run(); 
    } 
}; 
22

Zastosowanie schedule(Callable<V>, long, TimeUnit) zamiast scheduleAtFixedRate lub scheduleWithFixedDelay. Następnie upewnij się, że Twój Callable zmieni się sam lub pojawi się nowa instancja z opcją wywołania w pewnym momencie w przyszłości. Na przykład:

// Create Callable instance to schedule. 
Callable<Void> c = new Callable<Void>() { 
    public Void call() { 
    try { 
    // Do work. 
    } finally { 
    // Reschedule in new Callable, typically with a delay based on the result 
    // of this Callable. In this example the Callable is stateless so we 
    // simply reschedule passing a reference to this. 
    service.schedule(this, 5000L, TimeUnit.MILLISECONDS); 
    } 
    return null; 
    } 
} 

service.schedule(c); 

Takie podejście pozwala na uniknięcie konieczności wyłączania i ponownie ScheduledExecutorService.

+0

Zamiast 'Callable ' możesz (należy?) Użyć 'Runnable'. – Thirler

+0

@Thirler: Tak, to jest słuszne. – Adamski

+0

Nie znajduję funkcji 'harmonogramu (wywoływania) dla usługi ScheduledExecutorService. Tylko te z wszystkimi parametrami. Czy możesz wskazać mi gdzie? Lub przynajmniej popraw ten przykład, aby uwzględnić opóźnienie 0. – jlanza

Powiązane problemy