线程池的设计与原理解析(四)之---runWorker()方法

在调用start()方法,调用的就是worker的run方法,实际上调用的是runWorker()方法

  public void run() {
            // 这个是核心方法,worker启动后的逻辑从这里进入
            runWorker(this);
        }

在这里插入图片描述
简单的梳理runWorker的流程

  • 如果构造worker的时候,指定了firstTask,那么首先执行firstTask。否则从队列中获取任务;
  • Worker线程会循环的getTask(),然后去执行任务
  • 如果getTask()为空,那么worker线程就会退出
  • 在任务执行前后,可以自定义扩展beforeExecute与afterExecuter方法
  • 如果检测到先吃池为STOP状态,并且线程还没有被中断过的话,进行中断处理

1.将初始执行task赋值给task

 Runnable task = w.firstTask;

2.completedAbruptly:是否是突然退出; false 正常退出; 默认ture

  boolean completedAbruptly = true;

3.条件判断

// 条件1: 指的是firstTask 不为 null.
// 条件2: 说明当前线程在queue中获取任务成功. 如果返回null。
// getTask是一个会阻塞线程的方法。说明当前线程需要执行退出逻辑
 (task != null || (task = getTask()) != null)   
   // w 就是启动worker
    final void runWorker(Worker w) {
        // wt == w.thread。
        Thread wt = Thread.currentThread();
        // 将初始 执行 task 赋值给 task
        Runnable task = w.firstTask;
        // 清空当前 w.firstTask引用
        w.firstTask = null;
        // 为了初始化worker 的 state == 0 和 exclusiveOwnerThread == null
        w.unlock(); // allow interrupts

        // 是否是突然退出 ; false 正常退出
        boolean completedAbruptly = true;
        try {
            // 条件1: 指的是firstTask 不为 null.
            // 条件2: 说明当前线程在queue中获取任务成功. 如果返回null。
            // getTask是一个会阻塞线程的方法。说明当前线程需要执行退出逻辑
            while (task != null || (task = getTask()) != null) {

                // worker加锁设置,为当前线程
                // 为什么要设置独占锁? shutdown时会判断当前worker状态,根据独占锁是否空闲来判断当前worker是否正在工作
                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

                // 条件1: 说明线程池目前处于 STOP/TIDYING.TERMINATION 此时线程一定要给它一个中断信号
                // 条件2: 前部分成立:说明当前线程池状态是>=STOP 且当前线程未设置中断状态;
                // 后半部分:
                // 强制刷新当前线程的中断标记 false, 有可能上一个task时,业务代码里面将当前线程的中断标记位设置为了true,且没有处理。
                // 这里一定要强制刷新一下,不会影响到后面的task
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())

                    //
                    wt.interrupt();
                try {
                    // 钩子方法,留给子类实现
                    beforeExecute(wt, task);
                    // 表现异常情况,如果thrown不为空,表示 task运行过程中,向上层抛出异常了
                    Throwable thrown = null;
                    try {
                        // task 可能是 FutureTask 也可能是Runnable接口实现类
                        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++;

                    // worker处理完成一个任务后,会释放独占锁。然后再次到queue队列中获取任务
                    w.unlock();
                }
            }
            // 什么情况执行到这里?
            // 1. getTask() 返回null。 说明当前线程应该执行退出
            // 2.
            completedAbruptly = false;
        } finally {
            // task.run() 抛出异常,直接到这里
            // 正常退出 completedAbruptly 为false
            // 异常退出 completedAbruptly 为 true
            processWorkerExit(w, completedAbruptly);
        }
    }

总结:runWorker
1.如果task不为空,则开始执行task方法
2.如果task为空,则通过getTask()再去取任务,并赋值给task,如果取到的Runnable不为空,则执行该任务;
3.执行完毕后,通过while循环继续getTask()取任务
4.如果getTask()取到的任务依然是空,那么整个runWorker()方法执行完毕;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

virtuousOne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值