天天看点

线程池源码之-execute为什么执行完后main不退出1、现象2、源码3,结束办法:

1、现象

main方法执行线程池后 发现线程创建完毕 但是mian 方法一直卡在那里无法退出

2、源码

2.1、执行execute后代码如下

注意看下面的addworker

class: java.util.concurrent.ThreadPoolExecutor

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        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);
    }
           

2.2、执行start会回调run方法

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        **
        **
        ..
        ..
        **
        /** Delegates main run loop to outer runWorker  */
        public void run() {
            runWorker(this);
        }
           

2.3、runworker下有个死循环

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) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
           

2.4、继续查看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;
            }
        }
    }
           

如果无超时时间,则不会结束

3,结束办法:

但是实际测试时候发现这里并不是死循环  只是一直去取  如果没任务就没了

实际测试  如果设置线程池为守护进程 就会退出(默认是非守护进程) 这个跟jvm有关

setDaemo(false);

参考:https://www.yuque.com/u1300481/kb/gr403g

参考:https://www.jianshu.com/p/7c7eb33a4424