JAVA线程池的实现原理

为了阅读方便,部分代码有所简化

创建

了解源码最主要的就是找入口,入口找到了,就可以一步步往下面看了。那么线程池的入口在哪里呢?当然是从创建线程池的地方开始。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              RejectedExecutionHandler handler)

corePoolSize:线程池核心线程数量

maximumPoolSize:线程池最大线程数量

keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间

unit:存活时间的单位

workQueue:存放任务的队列

handler:超出线程范围和队列容量的任务的处理程序

使用

使用线程池的时候是调用了execute方法执行我们创建的线程,下面看execute方法源码
execute(Runnable command)

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        //情况1.核心线程未达到corePoolSize设定的值
        if (workerCountOf(c) < corePoolSize) {
        	//添加工作线程方法
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //情况2.核心线程已达到corePoolSize设定的值但队里未满
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);     //调用handler超出线程范围和队列容量的任务的处理程序
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //情况3.核心线程已满且队列已满
        else if (!addWorker(command, false))
            reject(command);        //调用handler超出线程范围和队列容量的任务的处理程序
    }
//调用handler超出线程范围和队列容量的任务的处理程序
final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

可以看到使用线程池的时候会有三种情况

  1. 核心线程未达到corePoolSize设定的值
  2. 核心线程已达到corePoolSize设定的值但队里未满
  3. 核心线程已满且队列已满

我们一种一种来说,先说第一种情况

情况1,核心线程未达到corePoolSize设定的值:
可以看到当核心线程未满时,会调用addWorker()方法来添加核心线程,下面看addWorker()方法

private boolean addWorker(Runnable firstTask, boolean core) {
        Worker w = null;
        for (;;) {
                int wc = workerCountOf(c);
                //判断核心线程数是否大于maximumPoolSize.如果大于的话就返回。
                if (wc >= CAPACITY ||wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
            }
        try {
        	//把执行任务包装成一个Worker对象,这里的Worker对象实际上也是一个线程
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    int rs = runStateOf(ctl.get());
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive())
                            throw new IllegalThreadStateException();
                        //把前面的Worker对象添加的workers中
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                	//启动Worker线程
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

Worker类也是一个线程对象

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
	    public void run() {
            runWorker(this);
        }
    }

可以看到Worker也是实现了Runnable接口,上面的t.start()调用的实际上是启动了Worker线程,也就是调用了此处的run()方法,run()调用了runWorker()方法,下面看runWorker()方法

final void runWorker(Worker w) {
	Runnable task = w.firstTask;
	try {
		//循环从workQueue中取出任务并执行。getTask()方法在workQueue中没有任务的时候会堵塞,直到有任务加入或超时结束退出。
		//firstTask为前面传进来的任务,getTask为从workQueue获取任务执行
	    while (task != null || (task = getTask()) != null) {
		     try {
		         task.run();
		     } finally {
		      	//省略其他代码
		     }
	    }
	} finally {
		processWorkerExit(w, completedAbruptly);
	}
}
private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();//会堵塞线程,直到workQueue中有新任务的加入
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

可以看到有个while循环,这个while循环干的事就是先执行传进来的Worker中封装的线程,然后通过getTask()循环把队列中的任务取出来执行。如果getTask方法结束,返回的是null,runWorker循环结束,执行processWorkerExit方法。
至此,该线程结束自己的使命,从线程池中“消失”。

情况2:
比较简单,就是调用workQueue的offer方法把线程加入到队列中,供已经存在的核心线程取出来执行。

情况3:
会再次尝试调用addWorker()再次添加工作线程,但是会限制在maximumPoolSize之内。

你可能感兴趣的:(java,java线程池,java线程池原理,java线程池源码,java基础到深入专栏)