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?
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.
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.
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.
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:
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
...
Tags und Links java concurrency scheduled-tasks threadpool