метод 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