workerCountOf() метод в ThreadPoolExecutor java

Опитвам се да разбера класа ThreadPoolExecutor. Намерих някои крайни променливи, декларирани в този клас и не мога да разбера употребата им.

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;         //29
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;    //536870911     00011111111111111111111111111111

// RUN_STATE is stored in the high-order bits
private static final int RUNNING    = -1 << COUNT_BITS;         //-536870912    11100000000000000000000000000000
private static final int SHUTDOWN   =  0 << COUNT_BITS;         //0             00000000000000000000000000000000
private static final int STOP       =  1 << COUNT_BITS;         //536870912     00100000000000000000000000000000
private static final int TIDYING    =  2 << COUNT_BITS;         //1073741824    01000000000000000000000000000000
private static final int TERMINATED =  3 << COUNT_BITS;         //1610612736    01100000000000000000000000000000

По-горе са крайните променливи и техните двоични и десетични стойности.

След това открих два метода с използването на тези променливи:

private static int runStateOf(int c)     { return c & ~CAPACITY; }  // RUN_STATE & ~CAPACITY = RUN_STATE
private static int workerCountOf(int c)  { return c & CAPACITY; }   // RUN_STATE & CAPACITY = 0
private static int ctlOf(int rs, int wc) { return rs | wc; }

Коментарите преди методите са резултатът, който наблюдавах.

Сега в метод ThreadPoolExecutor#execute(runnable),

Той прави следното изчисление с израз като If fewer than corePoolSize threads are running

int c = ctl.get();
if (workerCountOf(c) < corePoolSize)

Опитвам се да разбера, в който случай стойността на workerCountOf(c) може да бъде по-голяма от corePoolSize. Както можете да видите, първоначалната стойност на ctl е RUNNING.

Освен това има методи за добавяне и намаляване на ctl стойности атомарно,

private boolean compareAndIncrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect + 1);
}

private boolean compareAndDecrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect - 1);
}

Сега да кажем, че работят 5 нишки, така че ctl = RUNNING + 5,

Дори тогава workerCountOf(ctl.get()) = 0,

As ((RUNNING+5) & CAPACITY) = 0.

Може ли някой да ми обясни причината за създаването на тези крайни променливи и тяхното използване?

Как методът workerCountOf() всъщност връща нито един от изпълняваните нишки?

Сигурно пропускам нещо.

Благодаря


person akash777.sharma    schedule 03.09.2016    source източник


Отговори (1)


Както можете да видите, Java използва полето int ctl, за да съхранява както текущото състояние на пула, така и броя на нишките. Състоянието се съхранява в по-високите три бита, а всички останали битове се използват за съхраняване на броя на нишките. Побитовата маска CAPACITY се използва за разделянето им един от друг:

  • CAPACITY = 00011111111111111111111111111111
  • ~CAPACITY = 11100000000000000000000000000000

По този начин,

  • ctl & CAPACITY запазва по-малките 29 бита и нулира по-високите три бита; резултатът е текущият номер на нишки
  • ctl & ~CAPACITY запазва по-високите три бита и нулира всички останали; резултатът е състоянието на изпълнение на пула

Както правилно забелязахте, работещият пул с пет нишки има ctl = (RUNNING + 5), който има двоично представяне 111000...000101. И така, прилагането на маската CAPACITY нулира най-високите три бита и ви дава стойност 000000...000101, която е 5, а не 0.

person Andrew Lygin    schedule 03.09.2016