Was ist der beste Weg, eine gebundene Warteschlange mit ScheduledThreadPoolExecutor zu haben?

9

Das Sun Java (1.6) ScheduledThreadPoolExecutor , das eine Erweiterung von ThreadPoolExecutor ist, verwendet intern eine Implementierung von DelayQueue , die eine unbegrenzte Warteschlange ist. Was ich brauche, ist ein ScheduledThreadpoolExecutor mit einer begrenzten Warteschlange , dh es hat eine Begrenzung für die Aufgaben, die sich in der Warteschlange ansammeln, so dass Aufgaben in der Warteschlange das Limit überschreiten und die weiteren übertragenen Aufgaben ablehnen und verhindern JVM geht aus dem Speicher.

Überraschenderweise hat google oder stackoverflow mich nicht auf Ergebnisse hingewiesen, die dieses Problem diskutieren. Gibt es eine solche Sache schon, die ich verpasse? Wenn nicht, wie kann ich einen ScheduledThreadpoolExecutor implementieren, um mir meine erwartete Funktionalität optimal zur Verfügung zu stellen?

    
Gopi 13.09.2011, 14:43
quelle

5 Antworten

3

Wie andere schon gesagt haben, gibt es dafür keine einfache Möglichkeit. Stellen Sie nur sicher, dass Sie versuchen, "Komposition" anstelle von "Vererbung" zu verwenden. Erstellen Sie eine neue Klasse, die die erforderliche Schnittstelle implementiert und an die zugrunde liegende ScheduledThreadPoolExecutor delegiert, indem Sie gemäß den erforderlichen Methoden Prüfungen durchführen.

Sie können auch die in dieser Thread mit einer einfachen Änderung. Anstatt Semaphore#acquire zu verwenden, können Sie Semaphore#tryAcquire verwenden und abhängig vom booleschen Ergebnis entscheiden, ob Sie den Ablehnungshandler aufrufen müssen oder nicht. Wenn ich darüber nachdenke, denke ich persönlich, dass es ein Versehen seitens der Bibliotheksautoren war, einen spezifischen Executor direkt abzuleiten, anstatt sich auf Komposition zu verlassen, um einen "planbaren" Wrapper über einen normalen Executor zu erstellen.

    
Sanjay T. Sharma 14.09.2011 05:53
quelle
1

Wie wäre es mit einer anderen Behandlung, d. h. abhängig von der Warteschlangengröße, wird die Task-Submission verzögert. Die Executor-Dienste machen die Warteschlange über getQueue () verfügbar. Sie können die size () -Option aufrufen und abhängig von der Begrenzung, die Sie für die Warteschlangengröße planen, können Sie entweder die Aufgaben ablehnen oder die Ausführung der Aufgabe verzögern (erhöhen Sie die geplante Zeit, wobei die Größe der Warteschlange als einer der Faktoren gilt) ).

Alles gesagt, das ist wieder nicht die beste Lösung; Just fyi, Java bietet Verzögerung Warteschlange, um Arbeitsstehlen zu unterstützen.

    
Scorpion 14.09.2011 05:47
quelle
1

Die einfachste Problemumgehung besteht darin, geplante Executor nur zum Planen von Tasks und nicht zum tatsächlichen Ausführen von Tasks zu verwenden. Scheduler müssen explizit die Größe der Executor-Warteschlange überprüfen und Task verwerfen, wenn die Executor-Warteschlange über einem Schwellenwert liegt.

Eine weitere Option ist die Überprüfung der ScheduledThreadPoolExecutor-Warteschlangengröße direkt in der geplanten Aufgabe. Wenn die Warteschlange über dem Schwellenwert liegt, kehren Sie einfach sofort zurück. In diesem Fall wird die Aufgabe sofort ausgeführt und aus der Warteschlange entfernt. Überlauf wird also nicht passieren.

    
Alexander Ashitkin 11.01.2012 10:10
quelle
0

Wenn Sie wirklich, wirklich ScheduledThreadPoolExecutor nicht erneut implementieren möchten, können Sie es erweitern und alle schedule* -Methoden überschreiben und Ihre eigenen Aufgabengrenzen implementieren. Es wäre jedoch ziemlich gemein:

%Vor%

Und wiederholen Sie für:

  • public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
  • public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
  • public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)

Hinweis: Dies wird nicht aufhören, Aufgaben zu wiederholen, die die Warteschlange überschreiten, sondern nur neu geplante Aufgaben zu blockieren.

Ein weiterer Nachteil ist, dass ich nicht auf irgendwelche Deadlock-Probleme geachtet habe, indem ich super.schedule aufgerufen habe, während ich die Sperre auf scheduleMonitor ...

gehalten habe     
SimonC 14.09.2011 05:35
quelle
0

ScheduledThreadPoolExecutor verwendet die Warteschlange nicht als Feld, sondern ruft getQueue auf. Aber es ruft super.getQueue auf, was eine Warteschlange von ThreadPoolExecutor ist. Sie können Reflektion verwenden, um es wie folgt zu überschreiben:

%Vor%     
logcat 25.01.2016 12:39
quelle