Frage

Ich versuche, einen ThreadPoolExecutor Zeitplan Aufgaben zu verwenden, aber mit ihrer Politik in einige Probleme laufen. Hier ist ihr erklärtes Verhalten:

  1. Wenn weniger als corePoolSize Threads laufen, immer die Executor einen neuen Thread vorzieht Hinzufügen statt Schlange stehen.
  2. Wenn corePoolSize oder mehrere Threads laufen, immer der Executor bevorzugt einen Antrag Queuing anstatt einen neuen Thread hinzufügen.
  3. Wenn eine Anfrage nicht Warteschlange gestellt werden kann, ein neuer Thread erstellt, es sei denn, dies maximumPoolSize überschreiten würde, wobei in diesem Fall, wird die Aufgabe abgelehnt werden.

Das Verhalten, das ich will, ist dies:

  1. wie oben
  2. Wenn mehr als corePoolSize aber weniger als maximumPoolSize Threads laufen, zieht es einen neuen Thread über Warteschlangen hinzufügen und mit einem Leerlauf-Thread über einen neuen Thread hinzufügen.
  3. wie oben

Im Grunde möchte ich nicht alle Aufgaben abgelehnt werden; Ich möchte, dass sie in einer unbegrenzten Warteschlange werden. Aber ich will maximumPoolSize Threads haben auf. Wenn ich eine unbegrenzte Warteschlange verwenden, erzeugt es nie Fäden, nachdem es coreSize trifft. Wenn ich eine begrenzte Warteschlange verwenden, lehnt sie Aufgaben. Gibt es eine Möglichkeit, um dieses?

Was ich denke darüber jetzt den ThreadPoolExecutor auf einem SynchronousQueue läuft, aber nicht Aufgaben direkt mit ihm Fütterung - anstatt sie zu einem separaten unbeschränkten LinkedBlockingQueue Fütterung. Dann ein anderer Thread-Feeds aus dem LinkedBlockingQueue in den Executor, und wenn man abgelehnt wird, ist es einfach versucht erneut, bis es nicht abgelehnt wird. Dies scheint wie ein Schmerz und ein bisschen wie ein Hack, obwohl - es ist ein sauberer Weg, dies zu tun

War es hilfreich?

Lösung

Ihr Anwendungsfall ist üblich, völlig legitim und leider schwieriger als man erwarten würde. Für Hintergrundinformationen können Sie dieser Diskussion lesen und finden ein Zeiger zu einer Lösung (auch in dem Thread erwähnt) hier . Shay-Lösung funktioniert gut.

Generell würde ich ein bisschen vorsichtig unbegrenzter Warteschlangen sein; es ist in der Regel besser explizite Anströmung Kontrolle zu haben, dass degradiert anmutig und das Verhältnis von Strom / verbleibende Arbeit regelt nicht entweder Hersteller oder Verbraucher zu überwältigen.

Andere Tipps

Es wahrscheinlich nicht notwendig ist Mikro-Management des Thread-Pools wie gewünscht wird.

Eine Cache-Thread-Pool wird wieder zu verwenden Leerlauf-Threads gleichzeitig potenziell unbegrenzte Anzahl gleichzeitiger Threads ermöglicht. Dies natürlich außer Kontrolle geratener Leistung erniedrigender aus dem Kontext führen könnte Overhead während stoßweise Perioden wechseln.

Executors.newCachedThreadPool();

Eine bessere Option ist eine Obergrenze für die Gesamtzahl der Threads zu platzieren, während des Verwerfen des Begriffs Leerlauf-Threads zu gewährleisten ersten verwendet werden. Die Konfigurationsänderungen wären:

corePoolSize = maximumPoolSize = N;
allowCoreThreadTimeOut(true);
setKeepAliveTime(aReasonableTimeDuration, TimeUnit.SECONDS);

über dieses Szenario Reasoning, wenn der Vollstrecker hat weniger als corePoolSize Fäden, als es nicht sehr beschäftigt sein muß. Wenn das System nicht sehr voll ist, dann gibt es wenig Schaden in Spinnen einen neuen Thread auf. Dadurch wird dazu führen, dass ThreadPoolExecutor immer einen neuen Arbeiter zu schaffen, wenn sie unter der maximalen Anzahl der Arbeiter erlaubt ist. Erst wenn die maximale Anzahl der Arbeitnehmer „läuft“ werden Arbeiter untätig warten Aufgaben gestellten Aufgaben werden. Wenn ein Arbeiter wartet ohne Aufgabe aReasonableTimeDuration, dann ist es erlaubt, zu beenden. Mit vernünftigen Grenzen für die Pool-Größe (schließlich gibt es nur so viele CPUs) und eine ziemlich große Timeout (halten Threads unnötig beendet), werden die gewünschten Vorteile wahrscheinlich zu sehen.

Die letzte Option ist hackish. Grundsätzlich ist die ThreadPoolExecutor verwendet intern BlockingQueue.offer zu bestimmen, ob die Warteschlangenkapazität hat. Eine kundenspezifische Implementierung von BlockingQueue kann immer den offer Versuch ablehnen. Wenn die ThreadPoolExecutor eine Aufgabe in die Warteschlange offer fehlschlägt, wird es versuchen, einen neuen Arbeiter zu machen. Wenn ein neuer Arbeiter nicht erstellt werden kann, wäre ein RejectedExecutionHandler aufgerufen werden. An diesem Punkt eine benutzerdefinierte RejectedExecutionHandler eine put in den benutzerdefinierten BlockingQueue zwingen könnte.

/** Hackish BlockingQueue Implementation tightly coupled to ThreadPoolexecutor implementation details. */
class ThreadPoolHackyBlockingQueue<T> implements BlockingQueue<T>, RejectedExecutionHandler {
    BlockingQueue<T> delegate;

    public boolean offer(T item) {
        return false;
    }

    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        delegate.put(r);
    }

    //.... delegate methods
}

Just Satz corePoolsize = maximumPoolSize und eine unbegrenzte Warteschlange verwenden?

In der Liste der Punkte, 1 schließt 2, da corePoolSize immer kleiner wird oder gleich als maximumPoolSize.

Bearbeiten

Es gibt immer noch etwas unvereinbar zwischen dem, was Sie wollen und was TPE werden Sie anbieten.

Wenn Sie eine unbegrenzte Warteschlange haben, wird maximumPoolSize so ignoriert, da man beobachtet, nicht mehr als corePoolSize Fäden jemals erstellt und verwendet werden.

Also, noch einmal, wenn Sie corePoolsize = maximumPoolSize mit unbeschränkter Warteschlange nehmen, haben Sie, was Sie wollen, nicht wahr?

Würden Sie suchen nach etwas mehr wie ein Cache gespeicherten Thread-Pool?

http : //download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool ()

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top