ThreadPoolExecutor'da çekirdek havuz boyutu ve maksimum havuz boyutu


Yanıtlar:


136

Gönderen bu blog yayınında :

Bu örneği ele alalım. Başlangıç ​​iş parçacığı havuzu boyutu 1, çekirdek havuz boyutu 5, maksimum havuz boyutu 10 ve kuyruk 100'dür.

İstekler geldikçe, en fazla 5 iş parçacığı oluşturulacak ve ardından görevler 100'e ulaşana kadar kuyruğa eklenecektir. Kuyruk dolduğunda en fazla yeni iş parçacığı oluşturulacaktır maxPoolSize. Tüm iş parçacıkları kullanımda olduğunda ve sıra dolduğunda görevler reddedilecektir. Kuyruk azaldıkça, aktif iş parçacığı sayısı da azalır.


Bu doğru mu? MaxPoolSize ulaşana kadar yeni iş parçacığı oluşturulacağını düşündüm. Daha sonra herhangi bir yeni iş parçacığı kuyruğa alınacaktır. Yanılıyorsam lütfen düzeltin ..
Kayma

4
Evet bu doğru. İş parçacığı yalnızca kuyrukta görevler varsa corePoolSize'ın ötesine eklenecektir. Sıra sıfıra ulaştıktan sonra bu ek iş parçacıkları "kaybolacak".
Luke

3
allowCoreThreadTimeOut(boolean)Çekirdek iş parçacığının belirli bir boşta kalma süresinden sonra öldürülmesine izin veren ilginç bir yöntem var. Bunu true olarak ayarlamak ve core threads= ayarlamak max threads, iş parçacığı havuzunun 0 ile max threads.
Jaroslaw Pawlak

4
Az önce buradan kopyaladınız bigsoft.co.uk/blog/index.php/2009/11/27/…
Kumar Manish

1
Reddedilen görevlere ne olur?
Balmumu

54

İş parçacıkları> corePoolSize & <maxPoolSize çalıştırılıyorsa , Toplam görev kuyruğu doluysa ve yenisi geliyorsa yeni bir İş Parçacığı oluşturun.

Form belgesi : ( CorePoolSize değerinden fazla ancak maksimumPoolSize iş parçacığından daha az çalışıyorsa, yeni bir iş parçacığı yalnızca kuyruk dolu olduğunda oluşturulur.)

Şimdi, basit bir örnek alın,

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

Burada, 5 corePoolSize'dir - Jvm'nin ilk 5 görev için yeni görev için yeni iş parçacığı oluşturacağı anlamına gelir. ve diğer görevler sıra dolana kadar sıraya eklenecektir (50 görev).

10 maxPoolSize'dir - JVM en fazla 10 iş parçacığı oluşturabilir. Halihazırda 5 görev / iş parçacığı çalışıyorsa ve kuyruk 50 bekleyen görevle doluysa ve sıraya bir yeni istek / görev daha geliyorsa, JVM 10'a kadar yeni iş parçacığı oluşturacaktır (toplam iş parçacığı = önceki 5 + yeni 5) ;

new ArrayBlockingQueue (50) = toplam kuyruk boyutudur - içinde 50 görevi sıraya koyabilir.

10 iş parçacığının tümü çalıştıktan sonra ve yeni görev gelirse, bu yeni görev reddedilecektir.

SUN tarafından dahili olarak Konu oluşturma kuralları:

  1. İş parçacığı sayısı corePoolSize değerinden azsa, yeni bir görevi çalıştırmak için yeni bir İş Parçacığı oluşturun.

  2. İş parçacığı sayısı corePoolSize'a eşitse (veya ondan büyükse), görevi kuyruğa koyun.

  3. Kuyruk doluysa ve iş parçacığı sayısı maxPoolSize değerinden azsa, görevleri çalıştırmak için yeni bir iş parçacığı oluşturun.

  4. Sıra doluysa ve iş parçacığı sayısı maxPoolSize değerinden büyük veya ona eşitse, görevi reddedin.

Umarım, Bu HelpFul .. ve lütfen yanlışsam düzeltin ...


21

Gönderen doc :

Yöntem çalıştırmada (java.lang.Runnable) yeni bir görev gönderildiğinde ve corePoolSize iş parçacıklarından daha azı çalıştığında, diğer çalışan iş parçacıkları boşta olsa bile isteği işlemek için yeni bir iş parçacığı oluşturulur. CorePoolSize değerinden fazla ancak maksimumPoolSize iş parçacığından daha az çalışıyorsa, yeni bir iş parçacığı yalnızca kuyruk doluysa oluşturulur.

Ayrıca:

CorePoolSize ve maximumPoolSize değerlerini aynı ayarlayarak, sabit boyutlu bir iş parçacığı havuzu oluşturursunuz. MaximumPoolSize değerini, Integer.MAX_VALUE gibi temelde sınırsız bir değere ayarlayarak, havuzun rastgele sayıda eşzamanlı görevi barındırmasına izin vermiş olursunuz. En tipik olarak, çekirdek ve maksimum havuz boyutları yalnızca yapım sırasında ayarlanır, ancak setCorePoolSize (int) ve setMaximumPoolSize (int) kullanılarak da dinamik olarak değiştirilebilir.


1) Yöntem çalıştırmada (java.lang.Runnable) yeni bir görev gönderildiğinde ve corePoolSize iş parçacıklarından daha azı çalışıyorsa, diğer çalışan iş parçacıkları boşta olsa bile isteği işlemek için yeni bir iş parçacığı oluşturulur. Boşta olan iş parçacıkları varsa, isteği yerine getirmek için neden yeni bir iş parçacığı oluşturmaya ihtiyaç var?
user2568266

1
2) CorePoolSize değerinden fazla ancak maksimumPoolSize iş parçacığından daha az çalışıyorsa, yeni bir iş parçacığı yalnızca kuyruk doluysa oluşturulur. Burada corePoolSize ve maximumPoolSize arasındaki farkı anlamıyorum. İkinci olarak, iş parçacıkları maximumPoolSize değerinden daha küçük olduğunda bir kuyruk nasıl dolabilir? Sıra yalnızca iş parçacıkları maximumPoolSize'a eşitse dolu olabilir. Değil mi?
user2568266

9

Fabrika sınıfını ThreadPoolExecutorkullanmak yerine manuel olarak oluşturmaya karar verirseniz Executors, kurucularından birini kullanarak bir tane oluşturmanız ve yapılandırmanız gerekecektir. Bu sınıfın en kapsamlı kurucusu:

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

Gördüğünüz gibi yapılandırabilirsiniz:

  • Çekirdek havuz boyutu (iş parçacığı havuzunun bağlı kalmaya çalışacağı boyut).
  • Maksimum havuz boyutu.
  • Canlı tutma süresi, bu, boşta kalan bir iş parçacığının parçalanmaya uygun olduğu zamandır.
  • Yürütülmeyi bekleyen görevleri tutmak için iş kuyruğu.
  • Bir görev gönderimi reddedildiğinde uygulanacak politika.

Sıraya Alınan Görevlerin Sayısını Sınırlandırma

Yürütülen eşzamanlı görevlerin sayısını sınırlamak, iş parçacığı havuzunuzu boyutlandırmak, uygulamanız ve yürütme ortamı için öngörülebilirlik ve kararlılık açısından büyük bir fayda sağlar: Sınırsız bir iş parçacığı oluşturma, sonunda çalışma zamanı kaynaklarını tüketir ve bunun sonucunda uygulamanız yaşayabilir , uygulama kararsızlığına bile yol açabilecek ciddi performans sorunları.

Bu, sorunun yalnızca bir kısmının çözümü: Yürütülen görevlerin sayısını sınırlıyorsunuz, ancak daha sonra yürütülebilecek ve sıraya konulabilecek işlerin sayısını sınırlamıyorsunuz. Uygulama daha sonra kaynak sıkıntısı yaşayacaktır, ancak gönderme hızı sürekli olarak yürütme oranını aşarsa sonuçta bu sorunu yaşayacaktır.

Bu sorunun çözümü şudur: Yürütücüye bekleyen görevleri tutmak için bir engelleme kuyruğu sağlamak. Kuyruğun dolması durumunda, gönderilen görev "reddedilecektir". RejectedExecutionHandlerBir görev gönderme reddedildiğinde çağırılır reddedilen fiil Önceki öğe alıntı neden yıllardan bu. Kendi reddetme politikanızı uygulayabilir veya çerçeve tarafından sağlanan yerleşik politikalardan birini kullanabilirsiniz.

Varsayılan ret politikaları, uygulayıcının bir RejectedExecutionException. Ancak, diğer yerleşik politikalar şunları yapmanıza izin verir:

  • Sessizce bir işi atın.
  • En eski işi atın ve son işi yeniden göndermeyi deneyin.
  • Arayan ileti dizisinde reddedilen görevi yürütün.

7

Kaynak

ThreadPoolExecutor havuz boyutu kuralları

Bir ThreadPoolExecutor'shavuzun boyutuyla ilgili kurallar genellikle yanlış anlaşılır çünkü olması gerektiğini düşündüğünüz şekilde veya istediğiniz şekilde çalışmaz.

Bu örneği ele alalım. Başlangıç ​​iş parçacığı havuzu boyutu 1, çekirdek havuz boyutu 5, maksimum havuz boyutu 10 ve kuyruk 100'dür.

Sun'ın yolu: istekler 5'e kadar iş parçacığı halinde geldikçe, görevler 100'e ulaşana kadar kuyruğa eklenecek. Sıra dolduğunda en fazla yeni iş parçacığı oluşturulacak maxPoolSize. Tüm iş parçacıkları kullanımda olduğunda ve sıra dolduğunda görevler reddedilecektir. Kuyruk küçüldükçe aktif iş parçacığı sayısı da azalır.

Kullanıcı tarafından tahmin edilen yol: istekler 10'a kadar iş parçacığı halinde geldikçe, görevler 100'e ulaşana kadar sıraya eklenecek ve bu noktada reddedilecektir. Sıra boşalana kadar iş parçacığı sayısı en fazla yeniden adlandırılacaktır. Kuyruk boşaldığında, iş parçacığı kalana kadar ölür corePoolSize.

Aradaki fark, kullanıcıların havuz boyutunu artırmaya daha erken başlamak istemeleridir ve kuyruğun daha küçük olmasını istemeleridir, burada Sun yöntemi havuz boyutunu küçük tutmak ve yalnızca yük çok arttığında artırmak ister.

İşte Sun'ın basit terimlerle iplik oluşturma kuralları:

  1. İş parçacığı sayısı daha azsa corePoolSize, yeni bir görevi çalıştırmak için yeni bir İş Parçacığı oluşturun.
  2. İş parçacığı sayısı ile eşitse (veya daha büyükse) corePoolSize, görevi kuyruğa alın.
  3. Kuyruk doluysa ve maxPoolSizeiş parçacığı sayısı daha azsa , görevleri çalıştırmak için yeni bir iş parçacığı oluşturun.
  4. Kuyruk doluysa ve iş parçacığı sayısı bu değerden büyük veya ona eşitse maxPoolSize, görevi reddedin. Uzun ve kısa olan, yeni iş parçacıklarının yalnızca kuyruk dolduğunda oluşturulmasıdır, bu nedenle sınırsız bir kuyruk kullanıyorsanız, iş parçacığı sayısı aşılmayacaktır corePoolSize.

Daha kapsamlı bir açıklama için, bunu atın ağzından alın: ThreadPoolExecutorAPI belgeleri.

ThreadPoolExecutorKod örnekleriyle nasıl çalıştığını anlatan gerçekten iyi bir forum yazısı var : http://forums.sun.com/thread.jspa?threadID=5401400&tstart=0

Daha fazla bilgi: http://forums.sun.com/thread.jspa?threadID=5224557&tstart=450


Teşekkür ederim. Cevabını çok beğendim. Altta yatan uygulamaya ışık saçar ve iş parçacığı havuzunun bu corePoolSize / maxPoolSize davranışını gerçekten anlamak için sorulması ve yanıtlanması GEREKEN soruları yanıtlar.
Pavel

3

Corepoolsize ve maxpoolsize terimlerinin tanımını javadoc'ta bulabilirsiniz. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

Yukarıdaki bağlantıda sorunuzun cevabı var. Ancak, sadece açıklığa kavuşturmak için. Uygulama, corePoolSize'a ulaşana kadar iş parçacığı oluşturmaya devam edecektir. Bence buradaki fikir, bu kadar çok iş parçacığının görev akışını idare etmek için yeterli olması gerektiğidir. CorePoolSize iş parçacıkları oluşturulduktan sonra yeni bir görev gelirse, görevler sıraya alınacaktır. Kuyruk dolduğunda, yürütücü yeni iş parçacıkları oluşturmaya başlayacaktır. Bu bir çeşit dengeleme. Esasen anlamı, görev akışının işleme kapasitesinden daha fazlası olmasıdır. Böylece, Executor Max iş parçacığı sayısına ulaşana kadar yeni iş parçacığı oluşturmaya başlayacaktır. Yine, ancak ve ancak kuyruk dolu olduğunda yeni bir iş parçacığı oluşturulacaktır.


3

Bu blogda iyi bir açıklama :

İllüstrasyon

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;
                }
            }
        }
    }
}

Çıktı :

---- 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

Java uyumluluğunun esasları kitabından :

CorePoolSize : ThreadPoolExecutor, yeni iş parçacığı yalnızca sıra dolu olduğunda başlatılana kadar kaç iş parçacığı başlayacağını belirleyen bir corePoolSize özniteliğine sahiptir

MaximumPoolSize : Bu öznitelik, en fazla kaç evrenin başlatıldığını belirler. Bunu Tamsayı olarak ayarlayabilirsiniz. Üst sınırın olmaması için MAX_VALUE


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

ThreadPoolExecutorYeni bir görevin sunulduğu zamanın dahili davranışını anlamak, nasıl corePoolSizeve maximumPoolSizefarklı olduğunu anlamama yardımcı oldu .

İzin Vermek:

  • Nhavuzdaki konu sayısı olabilir getPoolSize(),. Aktif konular + boş konular.
  • T yürütücüye / havuza gönderilen görevlerin miktarı.
  • Cçekirdek havuz boyutu olmak getCorePoolSize(),. Yeni görevler kuyruğa gitmeden önce gelen görevler için havuz başına en fazla kaç iş parçacığı oluşturulabilir .
  • Mmaksimum havuz boyutu olabilir getMaximumPoolSize(). Havuzun ayırabileceği maksimum iş parçacığı miktarı.

ThreadPoolExecutorYeni bir görev gönderildiğinde Java'nın davranışları :

  • Çünkü N <= Cboştaki iş parçacıklarına yeni gelen görev atanmaz, bunun yerine yeni bir iş parçacığı oluşturulur.
  • İçin N > Cve eğer boşta evre Yeni görev orada atanır sonra vardır.
  • İçin N > Cve HAYIR boşta konuları varsa, yeni görevler kuyruğuna konur. BURADA YENİ İPLİK OLUŞTURULMAMAKTADIR.
  • Sıra dolduğunda , kadar yeni iş parçacığı oluştururuz M. Eğer Mulaşıldığında, biz görevleri reddediyoruz. Burada olmaması gereken önemli olan, kuyruk dolana kadar yeni iş parçacığı oluşturmayacağımızdır!

Kaynaklar:

Örnekler

Kuyruk kapasitesi olan corePoolSize = 0ve maximumPoolSize = 10olan örnek 50.

Bu, kuyruğun içinde 50 öğe bulunana kadar havuzda tek bir etkin iş parçacığı ile sonuçlanacaktır.

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.

Kuyruk kapasitesi olan corePoolSize = 10ve maximumPoolSize = 10olan örnek 50.

Bu, havuzda 10 etkin iş parçacığı ile sonuçlanacaktır. Kuyrukta 50 öğe olduğunda görevler reddedilecektir.

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`. 

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.