设为首页 加入收藏

TOP

Java - ThreadPoolExecutor线程池分析(四)
2023-09-09 10:25:58 】 浏览:115
Tags:Java ThreadPoolExecutor 程池分
// 刚初始化的工作线程是不允许被中断的 setState(-1); // inhibit interrupts until runWorker // 第一次new的时候,会将任务赋值给firstTask this.firstTask = firstTask; // 给Worker构建Thread对象 this.thread = getThreadFactory().newThread(this); } /** 调用t.start(), 执行当前的run方法 */ public void run() { runWorker(this); } // Lock methods // 这里它自己实现了一套锁机制 (不可重入锁) // 中断线程不是立刻让线程停止,只是将thread的中断标识设置为true // // The value 0 represents the unlocked state. // The value 1 represents the locked state. protected boolean isHeldExclusively() { return getState() != 0; } protected boolean tryAcquire(int unused) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } protected boolean tryRelease(int unused) { setExclusiveOwnerThread(null); setState(0); return true; } public void lock() { acquire(1); } public boolean tryLock() { return tryAcquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isHeldExclusively(); } void interruptIfStarted() { Thread t; if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } } }

Worker对象中调用的runWorker方法

线程池添加线程成功就会调用 t.start() 方法启动Worker对象中线程,会去执行Worker对象中的run方法,run方法实际执行的是 runWorker(this) 方法。

执行任务的流程,并且做了中断线程相关的lock操作。

//  执行任务
final void runWorker(Worker w) {
    //  获取当前工作线程
    Thread wt = Thread.currentThread();
    //  获取Worker对象中封装的任务
    Runnable task = w.firstTask;
    //  将Worker的firstTask置为null
    w.firstTask = null;
    //  将Worker的state置为0,代表可以被中断
    w.unlock(); // allow interrupts
    //  任务执行时,勾子函数中是否出现异常标识位
    boolean completedAbruptly = true;
    try {
        //  获取任务的第一个方式,就是执行execute方法、submit方法,传入的任务直接处理
        //  获取任务的第二个方式,就是从工作队列中获取任务执行
        while (task != null || (task = getTask()) != null) {
            //  加锁,在SHUTDOWN状态下,当前线程不允许被中断
            //  并且Worker内部实现的锁,并不是重入锁,因为在中断时,也需要对Worker进行加锁,不能获取就代表当前线程正在执行任务
            w.lock();
            //  如果线程池状态发生了改变,变为了STOP状态,必需将当前线程中断
            //  第一个判断条件:判断当前线程池状态是否是STOP状态
            if ((runStateAtLeast(ctl.get(), STOP) 
                //  第二个判断条件: 查看中断标记位,并归位,如果为false,说明不是STOP,反之true,需要再次查看是否是并发操作导致线程池为STOP
                || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) 
            //  第三个判断条件: 查询当前线程的中断标记位,如果是false,就执行中断
            && !wt.isInterrupted())
                //  将中断标志置为true
                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  
                task = null;
                //  执行任务的任务个数加一
                w.completedTasks++;
                //  将state标识置为0
                w.unlock();
            }
        }
        //  如果勾子函数有异常是不会走到这里的
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

runWorker方法中的getTask方法

如何从工作队列workQueue中获取任务的。

//  从工作队列中获取任务
private Runnable getTask() {
    //  标识(非核心线程可以干掉)
    boolean timedOut = false; // Did the last poll() time out?
    //  死循环
    for (;;) {
        //  ==================判断线程池状态=======================

        //  获取ctl标识  
        int c = ctl.get();
        //  获取线程池的状态
        int rs = runStateOf(c);

        // 如果进入if,需要干掉当前工作线程
        // 线程池状态为 SHUTDOWN、 STOP
        // 如果线程池状态大于等于STOP,需要移除掉当前工作线程
        // 如果线程池状态为SHUTDOWN,并且工作线程为空,需要移除掉当前工作线程
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            //  当前工作线程计数器减一
            decre
首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇简述Spring Cache缓存策略 下一篇14、Spring之基于注解的声明式事务

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目