java线程池中的Worker解析

java线程池中的Worker解析

上一篇说到java线程池中添加真实的线程都是在Worker对象中完成的。今天看下Worker中是如何进行线程管理的。

上一篇说道coresize和maxsize两个池子的大小后,线程池会更具情况添加线程。添加线程主要依赖方法

addWorker(Runable command)方法,本篇将对addWorker方法进行详细分析。java.util.concurrent.ThreadPoolExecutor#addWorker方法

这里主要看重要的几行

w = new Worker(firstTask);
final Thread t = w.thread;
……
 if (workerAdded) {
t.start();
workerStarted = true;
}

这里线程实际就是Worker.thread对象。下面看下Worker

 Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

这里的thread来自在创建ThreadPoolExecutor中传入的ThreadFactory,该工厂方法用来按照模板创建线程。即方法

this.thread = getThreadFactory().newThread(this);

看下默认的工厂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;
        }

这里实际将worker对象作为runnable 对象传入进来,最终是new了一个Thread(最外层的worker的this实例),因此

最终t.start方法回调的就是这个传入的worker对象的run方法。所以直接看Worker类的run方法

 private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        /**
         * This class will never be serialized, but we provide a
         * serialVersionUID to suppress a javac warning.
         */
        private static final long serialVersionUID = 6138294804551838833L;

        /** Thread this worker is running in.  Null if factory fails. */
        final Thread thread;
        /** Initial task to run.  Possibly null. */
        Runnable firstTask;
        /** Per-thread task counter */
        volatile long completedTasks;

        /**
         * Creates with given first task and thread from ThreadFactory.
         * @param firstTask the first task (null if none)
         */
        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);
        }

run方法又调用了runWorker(this)方法

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

1 将传入worker对象中的thread成员放到一个临时的Runnable task中,然后将引用置位null(即代码中的 w.firstTask)

2 w.unlock方法,即可以中断

3 最重要的部分while循环

while (task != null || (task = getTask()) != null)

task即worker对象构造中传入的runable 即上一篇看到的comman,即真实的任务对象

如果task不为空,则进入后面的task.run方法,直接调用Runable对象的run方法。这里解释一下原因:

     整个动作是由工厂的Thread触发的:即工厂newThread出来的线程start方法

     3.1  start方法会回调Thread(Runnable r)构造器中r的run方法

     3.2  r 实际是一个worker的this引用,因此调用的是worker对象的run方法

     3.3  worker的run方法调用了runworker方法,最终到达while循环中的task.run方法

如果task为空,还需要判断getTask()是否为空

getTask方法是从阻塞队列BlockedQueue中去任务,即上一篇中第二个if判断中的queue.offer

getTask方法:

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

        retry:
        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;
            }

            boolean timed;      // Are workers subject to culling?

            for (;;) {
                int wc = workerCountOf(c);
                timed = allowCoreThreadTimeOut || wc > corePoolSize;

                if (wc <= maximumPoolSize && ! (timedOut && timed))
                    break;
                if (compareAndDecrementWorkerCount(c))
                    return null;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }

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

注意最后的代码:

 Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();

这里是一个三目运算符,但是结果都是

workQueue.poll或者workQueue.take

都是出队操作。

接着上面的while循环,下面这块代码主要是判断线程池状态如果再不正常情况下,线程中断

if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try 

然后是真正线程执行的部分

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

这里有三个回调方法

beforeExecute(wt, task);
task.run();
afterExecute(task, thrown);

其中beforeExecute和afterExecute可以在自己的任务中重写这两个方法。

最后在finally中

finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }

更新线程完成的数量

while结束后,执行

finally {
            processWorkerExit(w, completedAbruptly);
        }

这个processWorkerExit方法,这个方法主要是用来更新线程池中alive的数量

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

这里重点就这两句

 completedTaskCount += w.completedTasks;
            workers.remove(w);

完成数量+1

workers.remove掉w对象

为什么说是更新线程池中alive的数量呢,以为线程池getalivecount方法是这样的

public int getActiveCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int n = 0;
            for (Worker w : workers)
                if (w.isLocked())
                    ++n;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

便利workers中的所有worker,因此是remove后alivecount数量减少。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值