Kernpoolgröße im Vergleich zur maximalen Poolgröße in ThreadPoolExecutor


103

Was genau ist der Unterschied zwischen der Größe des Kernpools und der maximalen Poolgröße, wenn wir darüber sprechen ThreadPoolExecutor?
Kann es anhand eines Beispiels erklärt werden?



Antworten:


130

Aus diesem Blog-Beitrag :

Nehmen Sie dieses Beispiel. Die Größe des Start-Thread-Pools beträgt 1, die Größe des Kernpools 5, die maximale Poolgröße 10 und die Warteschlange 100.

Wenn Anfragen eingehen, werden Threads bis zu 5 erstellt, und dann werden Aufgaben zur Warteschlange hinzugefügt, bis sie 100 erreicht. Wenn die Warteschlange voll ist, werden neue Threads bis zu erstellt maxPoolSize. Sobald alle Threads verwendet werden und die Warteschlange voll ist, werden Aufgaben abgelehnt. Wenn sich die Warteschlange verringert, verringert sich auch die Anzahl der aktiven Threads.


Ist das richtig? Ich dachte, dass neue Threads erstellt werden, bis sie maxPoolSize erreichen. Dann werden alle neuen Threads in die Warteschlange gestellt. Bitte korrigieren Sie mich, wenn ich falsch
liege

4
Ja das ist korrekt. Threads werden nur über corePoolSize hinaus hinzugefügt, wenn sich Aufgaben in der Warteschlange befinden. Diese zusätzlichen Threads "sterben ab", nachdem die Warteschlange Null erreicht hat.
Luke

3
Es gibt eine interessante Methode allowCoreThreadTimeOut(boolean), mit der Core-Threads nach einer bestimmten Leerlaufzeit beendet werden können. Wenn Sie dies auf true setzen und core threads= setzen, max threadskann der Thread-Pool zwischen 0 und 0 skalieren max threads.
Jaroslaw Pawlak

4
Sie haben es gerade von hier kopiert bigsoft.co.uk/blog/index.php/2009/11/27/…
Kumar Manish

1
Was passiert mit den abgelehnten Aufgaben?
Wachs

52

IF laufenden Threads> corePoolSize & <MaxPoolSize , dann einen neuen Thread erstellen , wenn Gesamt - Task - Queue voll und neue ist ankommt.

Formular doc: (Wenn mehr als corePoolSize, aber weniger als maximalPoolSize- Threads ausgeführt werden, wird nur dann ein neuer Thread erstellt, wenn die Warteschlange voll ist.)

Nehmen Sie nun ein einfaches Beispiel:

ThreadPoolExecutor executorPool = new ThreadPoolExecutor(5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(50));

Hier ist 5 die corePoolSize - bedeutet, dass Jvm für die ersten 5 Aufgaben einen neuen Thread für eine neue Aufgabe erstellt. und andere Aufgaben werden der Warteschlange hinzugefügt, bis die Warteschlange voll ist (50 Aufgaben).

10 ist die maxPoolSize - JVM kann maximal 10 Threads erstellen. Bedeutet, wenn bereits 5 Aufgaben / Thread ausgeführt werden und die Warteschlange mit 50 ausstehenden Aufgaben voll ist und eine weitere neue Anforderung / Aufgabe in der Warteschlange eintrifft, erstellt JVM einen neuen Thread mit bis zu 10 (Gesamtzahl der Threads = vorherige 5 + neue 5) ;;

new ArrayBlockingQueue (50) = ist eine Gesamtgröße der Warteschlange - es können 50 Aufgaben in die Warteschlange gestellt werden.

Sobald alle 10 Threads ausgeführt werden und eine neue Aufgabe eintrifft, wird diese neue Aufgabe abgelehnt.

Regeln zum internen Erstellen von Threads durch SUN:

  1. Wenn die Anzahl der Threads geringer als corePoolSize ist, erstellen Sie einen neuen Thread, um eine neue Aufgabe auszuführen.

  2. Wenn die Anzahl der Threads gleich (oder größer als) der corePoolSize ist, stellen Sie die Aufgabe in die Warteschlange.

  3. Wenn die Warteschlange voll ist und die Anzahl der Threads geringer als maxPoolSize ist, erstellen Sie einen neuen Thread, in dem Aufgaben ausgeführt werden sollen.

  4. Wenn die Warteschlange voll ist und die Anzahl der Threads größer oder gleich maxPoolSize ist, lehnen Sie die Aufgabe ab.

Hoffe, das ist HelpFul .. und bitte korrigiere mich, wenn ich falsch liege ...


21

Aus dem Dokument :

Wenn eine neue Aufgabe in der Methode execute (java.lang.Runnable) übergeben wird und weniger als corePoolSize-Threads ausgeführt werden, wird ein neuer Thread erstellt, um die Anforderung zu verarbeiten, selbst wenn andere Arbeitsthreads inaktiv sind. Wenn mehr als corePoolSize, aber weniger als maximalPoolSize-Threads ausgeführt werden, wird ein neuer Thread nur erstellt, wenn die Warteschlange voll ist.

Außerdem:

Indem Sie corePoolSize und maximumPoolSize gleich einstellen, erstellen Sie einen Thread-Pool mit fester Größe. Indem Sie maximumPoolSize auf einen im Wesentlichen unbegrenzten Wert wie Integer.MAX_VALUE setzen, können Sie dem Pool erlauben, eine beliebige Anzahl von gleichzeitigen Aufgaben aufzunehmen. In der Regel werden die Kern- und Maximalpoolgrößen nur bei der Erstellung festgelegt, sie können jedoch auch dynamisch mit setCorePoolSize (int) und setMaximumPoolSize (int) geändert werden.


1) Wenn eine neue Aufgabe in der Methode execute (java.lang.Runnable) übergeben wird und weniger als corePoolSize-Threads ausgeführt werden, wird ein neuer Thread erstellt, um die Anforderung zu verarbeiten, selbst wenn andere Arbeitsthreads inaktiv sind. Warum muss ein neuer Thread erstellt werden, um die Anforderung zu verarbeiten, wenn inaktive Threads vorhanden sind?
user2568266

1
2) Wenn mehr als corePoolSize, aber weniger als maximalPoolSize-Threads ausgeführt werden, wird nur dann ein neuer Thread erstellt, wenn die Warteschlange voll ist. Ich verstehe den Unterschied zwischen corePoolSize und maximumPoolSize hier nicht. Zweitens, wie kann eine Warteschlange voll sein, wenn die Threads kleiner als maximalPoolSize sind? Die Warteschlange kann nur voll sein, wenn die Threads maximalPoolSize entsprechen. Ist es nicht?
user2568266

9

Wenn Sie eine ThreadPoolExecutormanuell erstellen möchten, anstatt die ExecutorsFactory-Klasse zu verwenden, müssen Sie eine mit einem ihrer Konstruktoren erstellen und konfigurieren. Der umfangreichste Konstruktor dieser Klasse ist:

public ThreadPoolExecutor(
    int corePoolSize,
    int maxPoolSize,
    long keepAlive,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    RejectedExecutionHandler handler
);

Wie Sie sehen können, können Sie Folgendes konfigurieren:

  • Die Größe des Kernpools (die Größe, bei der der Thread-Pool zu bleiben versucht).
  • Die maximale Poolgröße.
  • Die Keep-Alive-Zeit, nach der ein Leerlauf-Thread abgerissen werden kann.
  • Die Arbeitswarteschlange für Aufgaben, die auf ihre Ausführung warten.
  • Die Richtlinie, die angewendet werden soll, wenn eine Aufgabenübermittlung abgelehnt wird.

Begrenzen der Anzahl der Aufgaben in der Warteschlange

Die Begrenzung der Anzahl der gleichzeitig ausgeführten Aufgaben und die Größe Ihres Thread-Pools stellt einen großen Vorteil für Ihre Anwendung und ihre Ausführungsumgebung in Bezug auf Vorhersagbarkeit und Stabilität dar: Eine unbegrenzte Thread-Erstellung erschöpft möglicherweise die Laufzeitressourcen und Ihre Anwendung kann dies zur Folge haben , schwerwiegende Leistungsprobleme, die sogar zu Instabilität der Anwendung führen können.

Dies ist eine Lösung für nur einen Teil des Problems: Sie begrenzen die Anzahl der ausgeführten Aufgaben, aber nicht die Anzahl der Jobs, die für die spätere Ausführung gesendet und in die Warteschlange gestellt werden können. Bei der Anwendung tritt später eine Ressourcenknappheit auf, die jedoch möglicherweise auftritt, wenn die Übermittlungsrate konstant über der Ausführungsrate liegt.

Die Lösung für dieses Problem lautet: Bereitstellen einer Blockierungswarteschlange für den Executor, um die wartenden Aufgaben zu speichern. Wenn die Warteschlange voll ist, wird die übermittelte Aufgabe "abgelehnt". Das RejectedExecutionHandlerwird aufgerufen, wenn eine Aufgabenübermittlung abgelehnt wird, und deshalb wurde das abgelehnte Verb im vorherigen Element zitiert. Sie können Ihre eigene Ablehnungsrichtlinie implementieren oder eine der vom Framework bereitgestellten integrierten Richtlinien verwenden.

Die Standard-Ablehnungsrichtlinien lassen den Executor a auslösen RejectedExecutionException. Mit anderen integrierten Richtlinien können Sie jedoch:

  • Verwerfen Sie einen Job stillschweigend.
  • Verwerfen Sie den ältesten Job und versuchen Sie, den letzten erneut einzureichen.
  • Führen Sie die abgelehnte Aufgabe im Thread des Aufrufers aus.

5

Quelle

Regeln einer ThreadPoolExecutor-Poolgröße

Die Regeln für die Größe von a ThreadPoolExecutor's Pools werden im Allgemeinen falsch verstanden, da sie nicht so funktionieren, wie Sie es sich vorstellen oder wie Sie es möchten.

Nehmen Sie dieses Beispiel. Die Größe des Start-Thread-Pools beträgt 1, die Größe des Kernpools 5, die maximale Poolgröße 10 und die Warteschlange 100.

So geht's: Wenn Anfragen in Threads eingehen, werden bis zu 5 erstellt, dann werden Aufgaben zur Warteschlange hinzugefügt, bis sie 100 erreicht. Wenn die Warteschlange voll ist, werden neue Threads bis zu 5 erstellt maxPoolSize . Sobald alle Threads verwendet werden und die Warteschlange voll ist, werden Aufgaben abgelehnt. Wenn sich die Warteschlange verringert, verringert sich auch die Anzahl der aktiven Threads.

Vom Benutzer erwartete Art und Weise: Wenn Anforderungen in Threads eingehen, werden bis zu 10 erstellt, und Aufgaben werden der Warteschlange hinzugefügt, bis sie 100 erreicht und an diesem Punkt abgelehnt werden. Die Anzahl der Threads wird maximal umbenannt, bis die Warteschlange leer ist. Wenn die Warteschlange leer ist, sterben die Threads ab, bis sie corePoolSizeübrig sind.

Der Unterschied besteht darin, dass die Benutzer die Poolgröße früher erhöhen und die Warteschlange kleiner machen möchten, während die Sun-Methode die Poolgröße klein halten und erst erhöhen möchte, wenn die Last zu groß wird.

Hier sind die Regeln von Sun für die Thread-Erstellung in einfachen Worten:

  1. Wenn die Anzahl der Threads geringer ist als die corePoolSize, erstellen Sie einen neuen Thread, um eine neue Aufgabe auszuführen.
  2. Wenn die Anzahl der Threads gleich (oder größer als) ist corePoolSize, stellen Sie die Aufgabe in die Warteschlange.
  3. Wenn die Warteschlange voll ist und die Anzahl der Threads geringer als die ist maxPoolSize, erstellen Sie einen neuen Thread, in dem Aufgaben ausgeführt werden.
  4. Wenn die Warteschlange voll ist und die Anzahl der Threads größer oder gleich ist maxPoolSize, lehnen Sie die Aufgabe ab. Das lange und das kurze daran ist, dass neue Threads nur erstellt werden, wenn die Warteschlange voll ist. Wenn Sie also eine unbegrenzte Warteschlange verwenden, wird die Anzahl der Threads nicht überschritten corePoolSize.

Eine ausführlichere Erklärung finden Sie im Pferdemund: ThreadPoolExecutorAPI-Dokumentation.

Es gibt einen wirklich guten Forumsbeitrag, der Ihnen zeigt, wie das ThreadPoolExecutormit Codebeispielen funktioniert: http://forums.sun.com/thread.jspa?threadID=5401400&tstart=0

Weitere Informationen: http://forums.sun.com/thread.jspa?threadID=5224557&tstart=450


3

Die Definition der Begriffe Corepoolsize und Maxpoolsize finden Sie im Javadoc. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

Der obige Link hat die Antwort auf Ihre Frage. Nur um es klar zu machen. Die Anwendung erstellt weiterhin Threads, bis sie die corePoolSize erreicht. Ich denke, die Idee hier ist, dass diese vielen Themen ausreichen sollten, um den Zufluss von Aufgaben zu bewältigen. Wenn eine neue Aufgabe kommt, nachdem die corePoolSize-Threads erstellt wurden, werden die Aufgaben in die Warteschlange gestellt. Sobald die Warteschlange voll ist, erstellt der Executor neue Threads. Es ist eine Art Ausgleich. Im Wesentlichen bedeutet dies, dass der Zufluss von Aufgaben mehr ist als die Verarbeitungskapazität. Executor erstellt also erneut neue Threads, bis die maximale Anzahl von Threads erreicht ist. Auch hier werden neue Threads erstellt, wenn die Warteschlange voll ist.


3

Gute Erklärung in diesem Blog:

Illustration

public class ThreadPoolExecutorExample {

    public static void main (String[] args) {
        createAndRunPoolForQueue(new ArrayBlockingQueue<Runnable>(3), "Bounded");
        createAndRunPoolForQueue(new LinkedBlockingDeque<>(), "Unbounded");
        createAndRunPoolForQueue(new SynchronousQueue<Runnable>(), "Direct hand-off");
    }

    private static void createAndRunPoolForQueue (BlockingQueue<Runnable> queue,
                                                                      String msg) {
        System.out.println("---- " + msg + " queue instance = " +
                                                  queue.getClass()+ " -------------");

        ThreadPoolExecutor e = new ThreadPoolExecutor(2, 5, Long.MAX_VALUE,
                                 TimeUnit.NANOSECONDS, queue);

        for (int i = 0; i < 10; i++) {
            try {
                e.execute(new Task());
            } catch (RejectedExecutionException ex) {
                System.out.println("Task rejected = " + (i + 1));
            }
            printStatus(i + 1, e);
        }

        e.shutdownNow();

        System.out.println("--------------------\n");
    }

    private static void printStatus (int taskSubmitted, ThreadPoolExecutor e) {
        StringBuilder s = new StringBuilder();
        s.append("poolSize = ")
         .append(e.getPoolSize())
         .append(", corePoolSize = ")
         .append(e.getCorePoolSize())
         .append(", queueSize = ")
         .append(e.getQueue()
                  .size())
         .append(", queueRemainingCapacity = ")
         .append(e.getQueue()
                  .remainingCapacity())
         .append(", maximumPoolSize = ")
         .append(e.getMaximumPoolSize())
         .append(", totalTasksSubmitted = ")
         .append(taskSubmitted);

        System.out.println(s.toString());
    }

    private static class Task implements Runnable {

        @Override
        public void run () {
            while (true) {
                try {
                    Thread.sleep(1000000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }
}

Ausgabe :

---- Bounded queue instance = class java.util.concurrent.ArrayBlockingQueue -------------
poolSize = 1, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 3, maximumPoolSize = 5, totalTasksSubmitted = 1
poolSize = 2, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 3, maximumPoolSize = 5, totalTasksSubmitted = 2
poolSize = 2, corePoolSize = 2, queueSize = 1, queueRemainingCapacity = 2, maximumPoolSize = 5, totalTasksSubmitted = 3
poolSize = 2, corePoolSize = 2, queueSize = 2, queueCapacity = 1, maximumPoolSize = 5, totalTasksSubmitted = 4
poolSize = 2, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 5
poolSize = 3, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 6
poolSize = 4, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 7
poolSize = 5, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 8
Task rejected = 9
poolSize = 5, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 9
Task rejected = 10
poolSize = 5, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 10
--------------------

---- Unbounded queue instance = class java.util.concurrent.LinkedBlockingDeque -------------
poolSize = 1, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 2147483647, maximumPoolSize = 5, totalTasksSubmitted = 1
poolSize = 2, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 2147483647, maximumPoolSize = 5, totalTasksSubmitted = 2
poolSize = 2, corePoolSize = 2, queueSize = 1, queueRemainingCapacity = 2147483646, maximumPoolSize = 5, totalTasksSubmitted = 3
poolSize = 2, corePoolSize = 2, queueSize = 2, queueRemainingCapacity = 2147483645, maximumPoolSize = 5, totalTasksSubmitted = 4
poolSize = 2, corePoolSize = 2, queueSize = 3, queueRemainingCapacity = 2147483644, maximumPoolSize = 5, totalTasksSubmitted = 5
poolSize = 2, corePoolSize = 2, queueSize = 4, queueRemainingCapacity = 2147483643, maximumPoolSize = 5, totalTasksSubmitted = 6
poolSize = 2, corePoolSize = 2, queueSize = 5, queueRemainingCapacity = 2147483642, maximumPoolSize = 5, totalTasksSubmitted = 7
poolSize = 2, corePoolSize = 2, queueSize = 6, queueRemainingCapacity = 2147483641, maximumPoolSize = 5, totalTasksSubmitted = 8
poolSize = 2, corePoolSize = 2, queueSize = 7, queueRemainingCapacity = 2147483640, maximumPoolSize = 5, totalTasksSubmitted = 9
poolSize = 2, corePoolSize = 2, queueSize = 8, queueRemainingCapacity = 2147483639, maximumPoolSize = 5, totalTasksSubmitted = 10
--------------------

---- Direct hand-off queue instance = class java.util.concurrent.SynchronousQueue -------------
poolSize = 1, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 1
poolSize = 2, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 2
poolSize = 3, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 3
poolSize = 4, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 4
poolSize = 5, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 5
Task rejected = 6
poolSize = 5, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 6
Task rejected = 7
poolSize = 5, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 7
Task rejected = 8
poolSize = 5, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 8
Task rejected = 9
poolSize = 5, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 9
Task rejected = 10
poolSize = 5, corePoolSize = 2, queueSize = 0, queueRemainingCapacity = 0, maximumPoolSize = 5, totalTasksSubmitted = 10
--------------------


Process finished with exit code 0

1

Aus dem Buch Java Concurency Essentials :

CorePoolSize : Der ThreadPoolExecutor verfügt über ein Attribut corePoolSize, das bestimmt, wie viele Threads gestartet werden, bis neue Threads erst gestartet werden, wenn die Warteschlange voll ist

MaximumPoolSize : Dieses Attribut bestimmt, wie viele Threads maximal gestartet werden. Sie können dies auf Integer setzen. MAX_VALUE, um keine obere Grenze zu haben


0

java.util.concurrent.ThreadPoolExecutor

  public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

0

Das Verständnis des internen Verhaltens ThreadPoolExecutorbeim Einreichen einer neuen Aufgabe hat mir geholfen zu verstehen, wie corePoolSizeund wie sich diese maximumPoolSizeunterscheiden.

Lassen:

  • Ndie Anzahl der Threads im Pool sein , getPoolSize(). Aktive Threads + Leerlauf-Threads.
  • T Die Anzahl der Aufgaben, die an den Executor / Pool gesendet werden.
  • Cdie Kernpoolgröße sein , getCorePoolSize(). Wie viele Threads können höchstens pro Pool für die eingehenden Aufgaben erstellt werden, bevor neue Aufgaben in die Warteschlange gestellt werden .
  • Mdie maximale Poolgröße sein , getMaximumPoolSize(). Maximale Anzahl von Threads, die der Pool zuweisen kann.

Verhalten von ThreadPoolExecutorin Java beim Senden einer neuen Aufgabe:

  • Denn N <= Cden inaktiven Threads wird nicht die neue eingehende Aufgabe zugewiesen, sondern ein neuer Thread wird erstellt.
  • Für N > Cund wenn es freie Threads gibt, wird dort eine neue Aufgabe zugewiesen.
  • Für N > Cund wenn KEINE Leerlauf-Threads vorhanden sind, werden neue Aufgaben in die Warteschlange gestellt. HIER KEIN NEUES GEWINDE ERSTELLT.
  • Wenn die Warteschlange voll ist , erstellen wir neue Threads bis zu M. Wenn Merreicht, lehnen wir die Aufgaben ab. Was hier nicht wichtig ist, ist, dass wir keine neuen Threads erstellen, bis die Warteschlange voll ist!

Quellen:

Beispiele

Beispiel mit corePoolSize = 0und maximumPoolSize = 10mit einer Warteschlangenkapazität von 50.

Dies führt zu einem einzelnen aktiven Thread im Pool, bis die Warteschlange 50 Elemente enthält.

executor.execute(task #1):

before task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]

after task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]

[task #1 immediately queued and kicked in b/c the very first thread is created when `workerCountOf(recheck) == 0`]

execute(task #2):

before task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]

after task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@c52dafe[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]

[task #2 not starting before #1 is done]

... executed a few tasks...

execute(task #19)

before task #19 submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 1, active threads = 1, queued tasks = 17, completed tasks = 0]

after task #19 submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 1, active threads = 1, queued tasks = 18, completed tasks = 0]

...

execute(task #51)

before task submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 1, active threads = 1, queued tasks = 50, completed tasks = 0]

after task submitted to executor: java.util.concurrent.ThreadPoolExecutor@735afe38[Running, pool size = 2, active threads = 2, queued tasks = 50, completed tasks = 0]

Queue is full.
A new thread was created as the queue was full.

Beispiel mit corePoolSize = 10und maximumPoolSize = 10mit einer Warteschlangenkapazität von 50.

Dies führt zu 10 aktiven Threads im Pool. Wenn die Warteschlange 50 Elemente enthält, werden Aufgaben abgelehnt.

execute(task #1)

before task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]

after task #1 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]

execute(task #2)

before task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]

after task #2 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]

execute(task #3)

before task #3 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]

after task #3 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]

... executed a few tasks...

execute(task #11)

before task #11 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 10, active threads = 10, queued tasks = 0, completed tasks = 0]

after task #11 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 10, active threads = 10, queued tasks = 1, completed tasks = 0]

... executed a few tasks...

execute(task #51)
before task #51 submitted to executor: java.util.concurrent.ThreadPoolExecutor@32d9e072[Running, pool size = 10, active threads = 10, queued tasks = 50, completed tasks = 0]

Task was rejected as we have reached `maximumPoolSize`. 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.