接上一篇,简单学习一下java线程池的运行原理

首先回顾一下java线程池的架构
在这里插入图片描述

进入正题,java线程池的执行步骤

1.创建线程池->submit或execute(提交任务)

上篇中说过,其实submit()底层调用的还是execute()。
看源码:在这里插入图片描述
java线程池的顶级接口Executor下就一个方法execute();最终实现这个方法的是在ThreadPoolExecutor类中
在这里插入图片描述

2.添加任务(addWorker())

添加任务分四种情况:看源码中,addWorker()前执行了多个if语句,如下图:四个框就是分四种情况。
在这里插入图片描述

**第一种情况:**当前线程数小于核心线程数,如下这段代码:

 if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }

执行addWorker(command, true)
参数:command:就是提交执行的任务
true:就代表走核心线程数,false:就代表走最大线程数=>看源码说话:
在这里插入图片描述
第二种情况: 当前线程数大于核心线程数的情况 ,就会执行workQueue.offer(command)
添加任务到阻塞队列,等待执行。如下这段代码:

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);
        }

阻塞队列,用来存储等待执行的任务,决定了线程池的排队策略,有以下取值:
  ArrayBlockingQueue;
  LinkedBlockingQueue;
  SynchronousQueue;

第三种情况: 如果当前线程数大于核心数并且阻塞队列也满了,但是小于最大线程数的情况,就会新建一个核心线程 然后addWorker(command, false)上边说到了,参数false就是走的最大线程数。

第四种情况: 以上条件都不满足,则执行拒绝策略。reject(command)
记住拒绝策略有四种,划重点考试要考:在这里插入图片描述
其中,AbortPolicy是默认的拒绝策略,就是直接抛异常,不信看源码说话:
在这里插入图片描述
CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务
DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
DiscardPolicy();//丢任务不异常

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 {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

Runnable task = w.firstTask;先把核心线程中的任务拿出来给task,
核心线程中的任务执行完才会执行阻塞队列中的任务,
while 条件语句中有task = getTask(),就是从队列中取出任务并给task
下边有task.run();就是执行任务。

4.执行完毕,流程结束(processWorkerExit())

看上边runWorker源码中,最终的finally 里执行了processWorkerExit(w, completedAbruptly)
咱们进去看看源码:

private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        tryTerminate();

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            addWorker(null, false);
        }
    }

上边不用看,看最后是不是又回到addWorker了。这就是线程池的重复利用,一条任务线程执行完有回到addWorker,重复如此,直到天荒地老,海枯石烂。。。直到你关闭线程池调用,上一篇说过线程池关闭的方式。

5.总结

总结两张图,通俗易懂,自己画的,难看什么的无所谓吧。
执行流程:

在这里插入图片描述
四种情况:
在这里插入图片描述
纯属自己的理解,小白一个,说的不对的地方望见谅,评论提出修改。

再见老铁!

发布了12 篇原创文章 · 获赞 22 · 访问量 2615

猜你喜欢

转载自blog.csdn.net/weixin_45240169/article/details/103699237