线程池细节详解ThreadPoolExecutor

关于线程池的几个参数的含义,我们就不多说了,下面我们通过源码看下这几个参数分别是在什么地方使用到的:

核心池大小与最大池大小是在执行任务的时候用到的,这里我们不多说。

当线程池中没有任务,线程池就会维持核心池大小的线程,这个源码如下:

当线程进来会先被封装成一个Worker类,这个类实现了Runnable接口,如下:

    private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

        /** Delegates main run loop to outer runWorker  */
        public void run() {
            runWorker(this);
        }

实际上,线程池创建的线程,是先执行的这个Worker类的run方法,然后才执行Runnable类的run方法,即为封装了一层,如下:

Runnable task = w.firstTask;
task.run();
final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {

runWorker中有一个getTask()方法,我们着重来看这个方法,里面就有为什么核心线程数的线程可以一直存在的秘密:

    private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

上面可以看到,如果当前线程数(wc>corePoolSize)的话,则执行阻塞队列的poll方法,否则执行take()方法,而poll方法中,传入了一个keepAliveTIme的参数,此时空闲线程会等keepalive的时间,如果取不到数据则返回空,当前线程走完结束,如果执行take()方法,则会一直阻塞,知道取到数据,这就是为什么核心线程池一直存在的原因。

同时我们还看到一个allowCoreThreadTimeOut参数,这个参数默认值是false,如果不想让核心线程存在也可以主动将此参数设置为true。


另外还有一个可以说下的就i是ThreadFactory,它创建线程的方式跟我们平时创建线程用的方式是一样的:

this.thread = getThreadFactory().newThread(this);
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
也就是new了一个线程这样而已。ThreadFactory只是创建线程用的,在线程创建好后,就跟ThreadFactory完全没有关系了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值