Java提供的几个线程池,最终都是使用 ThreadPoolExecutor 这个类来实现的。

先看点基础的。

暂时不一上来就看怎么创建线程池,以及各个参数的作用等,先基本的走起。

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

    // runState is stored in the high-order bits
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

    // Packing and unpacking ctl
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }

    /*
     * Bit field accessors that don't require unpacking ctl.
     * These depend on the bit layout and on workerCount being never negative.
     */

    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }

    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }

    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }

源码里面有这么点属性和简单方法,都是最基本的,绕不开的东西。了解一下。

java 线程池keepAliveTime属性 java 线程池状态_多线程

1,首先是一个原子类 AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 

这个是在多线程操作的时候,记录线程池的一些状态和池里面线程的数量的载体。使用原子类,是为了线程安全。

源码中说,现阶段,暂时使用一个int类型的数字来表示信息,基本差不多够用了,里面可以包含2的29次方-1的线程数,差不多500million(百万),源码注释这么写的。要是后期不够用了,还可以扩展为long类型

2,int  类型的 COUNT_BITS = Integer.SIZE - 3;

/**
     * COUNT_BITS 详解
     */
    @Test
    public void showCountBits() {
        // 29 Integer.SIZE=32 意思就是integer使用了多少位来表达一个int数字。
        System.out.println(Integer.SIZE);
        // 4个字节,一个字节(byte)8位(bit)
        System.out.println(Integer.BYTES);
        System.out.println(COUNT_BITS);
        System.out.println();
    }

运行结果:

java 线程池keepAliveTime属性 java 线程池状态_java_02

这个就解释了,这个数字  29哪里来的。

这个属性,就是说 int 类型 的 属性  ctl 的(二进制)29个二进制位来表示 work counter ,暂时没说是哪29个二进制位。

3,int 类型的 CAPACITY   = (1 << COUNT_BITS) - 1;

@Test
    public void showCapacity() {
        // 二进制:000 + 29个1,的int值。
        showOne("CAPACITY", CAPACITY);
        // 二进制:111 + 29个0,的int值
        showOne("~CAPACITY", ~CAPACITY);


        int i = 7 & CAPACITY;
        System.out.println("111 & CAPACITY: " + (Integer.toBinaryString(i)));
        System.out.println();

        // 32位中,第一位是0,其它的都是1,即 Integer.MAX_VALUE = 0 + 31 个1
        System.out.println("Integer.MAX_VALUE 二进制:" + Integer.toBinaryString(Integer.MAX_VALUE));
        System.out.println("Integer.MAX_VALUE 二进制的长度:" + Integer.toBinaryString(Integer.MAX_VALUE).length());
        i = Integer.MAX_VALUE & ~CAPACITY;
        System.out.println("Integer.MAX_VALUE & ~CAPACITY: " + (Integer.toBinaryString(i)));
        System.out.println("Integer.MAX_VALUE & ~CAPACITY: " + (Integer.toBinaryString(i)).length());
    }

运行结果:

java 线程池keepAliveTime属性 java 线程池状态_多线程_03

容量:1左移29位 = 1后面29 个0,再减1 ,就等于29个1。就表示了容量,capacity单词也是这个意思。

取反之后,就是 111(3个1的二进制位)+29个0,然后 & 与运算,

runStateOf()方法是对 ~CAPACITY 与运算的,其实就是取int的前3位的值

workerCountOf()方法是对 CAPACITY 与运算的,其实就是取int的后29位的值

由此,int属性的32个二进制位都用来干吗的就分配完了。

4,线程池的几个状态

// runState is stored in the high-order bits
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

    /**
     * 看看线程池的几个状态数字
     * 这么看就明白了后面29个位,来控制线程的数量count,前面3位来表示线程池的状态,全1的即111表示running,
     * 000-011是递增关系,同时也是线程池状态的衰败过程。
     */
    @Test
    public void showState() {
        //111 - (29个0)
        showOne("RUNNING", RUNNING);
        //000 - (29个0)
        showOne("SHUTDOWN", SHUTDOWN);
        //001 - (29个0)
        showOne("STOP", STOP);
        //010 - (29个0)
        showOne("TIDYING", TIDYING);
        //011 - (29个0)
        showOne("TERMINATED", TERMINATED);
    }

运行结果:

java 线程池keepAliveTime属性 java 线程池状态_java_04

这么看一下,线程池的几个状态,其实就是int的前3位来表示的;

全1的即111表示running,

java 线程池keepAliveTime属性 java 线程池状态_java_05

(-1 << 29  :那就是32个1,左移29位,那就只剩下111 + 29个0啦,running的状态就是这么来的。)

000-011是递增关系,同时也是线程池状态的衰败过程。还预留了些位置,以备后用。

线程池几个状态之间的关系变化图

java 线程池keepAliveTime属性 java 线程池状态_线程池_06

这个在源码的注释中也有写。

java 线程池keepAliveTime属性 java 线程池状态_Test_07

使用到的打印一个int数字的方法:

private void showOne(String name, int aInt) {
        System.out.println(name + "的信息");
        System.out.println("原始int值:" + aInt);
        System.out.println("二进制的值:" + Integer.toBinaryString(aInt));
        System.out.println("二进制的值的字符串的长度:" + Integer.toBinaryString(aInt).length());
        System.out.println("--------------------------");
        System.out.println();
    }

5,线程池的2个关键数字

/**
     * 线程池中的2个数字
     * 1,线程池的状态
     * 2,线程池中的线程数
     */
    @Test
    public void twoCountInPool() {
        int c = ctl.get();
        System.out.println("线程池的2个关键数字。。。");
        poolState(c);
        workerCount(c);
        System.out.println();
    }

    /**
     * 获取线程池的当前状态
     */
    private void poolState(int c) {
        System.out.println("线程池的状态。。。");
        int i = runStateOf(c);
        showOne("test state", i);
        System.out.println();
    }

    /**
     * 获取线程池中当前的线程数
     */
    private void workerCount(int c) {
        System.out.println("线程池的线程数。。。");
        int i = workerCountOf(c);
        System.out.println("worker count is " + i);
    }

运行结果:

java 线程池keepAliveTime属性 java 线程池状态_线程池_08

默认是running状态,0个worker。