一、前言
首先我们要知道线程是干什么的?线程就是执行任务的。所以 线程池这一块其实主要分为两个部分:第一个就是被执行的任务——Task,我们这里名为纵;第二个是执行任务的——ThreadPoolExecutor,我们这里名为横。只要合纵连横就可以达到线程池的效果。本文先主要聊聊ThreadPoolExecutor提交Runable和Callable执行流程和原理,至于线程池的运行流程和逻辑以后再说。
二、纵
1. Runable(接口)
Runable是我们最熟悉的线程接口,它只有一个run()方法,是一个顶层接口。没有返回值,实现Runable接口的类就是一个没有返回值的任务;
2. Callable(接口)
Callable是另一个线程接口,它也是一个顶层接口,只有一个call()方法,与Runable不同的是它有返回值。
3.Future(接口)
Future可以说是为Callable定做的一个接口。因为线程间的运行是异步的,所以当你试图去拿到Callable的返回值时,该线程可能还没结束。所以用Future预保存Callable的返回值。当试图获取Callable的返回值时,调用Future的get()方法(由具体的实现类实现该方法),如果Callable执行完毕,那么就直接返回值;如果Callable未执行完毕,那么将阻塞获取返回值,直到Callable执行完毕。
4. RunnableFuture(接口)
RunnableFuture也是一个接口,同时继承了Runable和Future接口,拥有二者的功能,但是它只有一待实现方法run(),所以暂且把它看做一个升级版的Runable。
5. FutureTask(具体类,这个类中方法很多,功能也很多,这里只介绍一部分,感兴趣的同学可以自己去看看源码)
FutureTask是一个类,它实现了RunableFuture接口,这样相当于它拥有了Runable和Future的功能,而且,它还维护了一个Callable的变量。同时它还实现了Future里面的get()方法,可以用它接收Callable的返回值。这样通过它就相当于把Runable和Callable结合到了一起。
6. RunnableAdapter(具体类)
这是Callable的一个实现类,看名字知道是一个适配器,用于将Runable转换成Callable,实现了call()方法。它将Runable当做参数设置到自己的成员变量中,同时设置一个result=null作为返回结果(因为Runable没有返回值,二转成Callable后,call()方法又必须要有返回值,所以用空值做了一个假的返回值)。在call()方法中调用成员变量Runable的run()方法,同时返回result,这样就将Runable转换成Callable使用。
三、横
1. Executor(接口)
Executor从名字上看,它是一个执行器,负责执行任务。它只有一个execute()方法需要实现。
2.ExecutorService(接口)
ExecutorService是一个实现了Executor接口的接口,是对Executor的增强,尤其是增加了submit()方法,具体实现由它的实现类完成。可以理解为对线程池行为的规范,比如:线程池能关闭、提交任务等。
3.AbstractExecutorService(抽象类)
AbstractExecutorService是一个抽象类,实现了ExecutorService接口,它是对ExecutorService的增强,算实现了半个线程池的功能,它只实现了线程池的提交逻辑(比如:submit()方法、invokeAny()方法、invokeAll()方法)。
4.ThreadPoolExecutor(具体类)
ThreadPoolExecutor继承了AbstractExecutorService,相当于集成了上面1、2、3的功能,它实现了1、2接口中的方法,也从继承那里获得了3中类的方法,而且它自身实现了线程池剩下的全部功能和逻辑,是一个真正的完整的线程池。
四、合纵连横
弄清楚上面各个间的关系后,就可以合纵连横了。
首先记住两个重要结论(重要!重要!重要!):
a、线程池submit方法提交的所有任务(不管是Runable还是Callable),最终都是先被转成Callable,然后放在RunableFuture的实现类FutureTask的Callable属性中,最后以Runable形式使用execute方法执行;
b、线程池submit()方法提交的所有任务(不管是Runable还是Callable),最后start()方法运行的都是call()方法
上面两个结论对理解线程池的提交和执行逻辑非常重要,建议仔细体会。
1.证明结论a
//部分源码
AbstractExecutorService{
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
}
首先从源码中可以看到,无论提交的是Runable还是Callable任务,最后都被封装成了RunableFuture对象,RunableFuture上面已经介绍过了,这里可以理解为一个Runable。然后调用execute()方法执行。我们看Callable如何变成Runable,在newTaskFor()方法中,返回了一个FutureTask对象,上面介绍过了,FutureTask是RunnableFuture的实现类,这里是向上转型。下面看一下FutureTask()方法里面发生了什么。
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
可以看到FutureTask直接把Callable当做一个属性封装到自己内部,自己是一个Runable,相当于包含了Callable的Runable,然后执行Runable。
public FutureTask(Runnable runnable, V result) {
//这个Executors.callable()方法里面用的就是RunnableAdapter将Runable转为Callable
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
再看Runable,Runable并不因为你是Runable就直接使用execute()方法执行(讲道理这里是可以直接使用execute()方法执行的(例如:直接使用execute()方法提交Runable任务就是这样直接执行的,但直接使用execute()方法不能提交Callable任务。),但是它没这么写,如果有知道的可以告诉一下笔者为什么) ,它是将Runable对象通过RunnableAdapter转换成Callable,然后跟Callable逻辑一样被执行。
至此,结论a证明完毕!
2.证明结论b
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//当工作线程数小于核心线程数(比如刚启动,工作线程数为0)
if (workerCountOf(c) < corePoolSize) {
//添加核心线程,addWorker方法第二个参数决定核心线程和非核心线程,true为核心,false为非核心
if (addWorker(command, true))
return;
c = ctl.get();
}
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);
}
//这里是创建非核心线程
else if (!addWorker(command, false))
reject(command);
}
然后看addWorker源码,看如何创建核心和非核心线程
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//把接收到的Runable传到Worker的构造方法中,Worker也是一个Runable,然后调用Worker的start()方法,这里就相当于创建了一个新的线程
//这个方法很关键,建议细看,这里逻辑有些绕
w = new Worker(firstTask);
//这里的t就是w对象,没错w的属性是它自己,仔细理解,看下面源码
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//将新创建的线程放到线程队列(注意和任务队列区分)
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
//然后启动
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
然后我们看Worker的构造方法和run()方法,毕竟start()方法调用的是run()方法
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
//这个firstTask 就是我们提交的任务,最终转为Runable的形式提交到这里
this.firstTask = firstTask;
//这里Worker把自己封装到自己的属性中了
this.thread = getThreadFactory().newThread(this);
}
//调用Worker的start()方法,就会执行这个run()方法
public void run() {
runWorker(this);
}
//然后run()方法执行这里
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
//首先取出刚才封装到w中的firstTask,也就是我们传进去的Runable对象,其实更具体一点它是一个FutureTask对象,因为FutureTask实现了RunableFuture接口,RunableFuture实现了Runable接口,一定要理解前面各个类和接口的关系,不然这里很难看懂
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 {
//这里调用run()方法执行,你以为到这儿就完了吗?其实没有,我们可以看到这里并没有返回值,说明最终的run()方法并不在这里,没错,这里调用的只是FutureTask的run()方法,我们提交的是Runable或Callable任务,所以还得去看FutureTask的run()方法干了什么
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);
}
}
下面看看FutureTask的run()方法
FutureTask{
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
//首先拿到Callable对象,前面已经说过了,我们提交的Runable和Callable都会别封装到FutureTask的Callable属性中,这样的话只要调用call()方法,就可以实现我们自己提交的Runable和Callable里面的run()方法和call()方法了
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//对于提交的Callable任务,这里的call()方法就是我们实际重写的call()方法,并且返回result,这个result会存放到FutureTask的outcome属性中,当调用FutureTask的get()方法时可以取出。
//对于提交的Runable任务,这里的call()方法是我们将Runable用RunnableAdapter转换成Callable后的call()方法**(结论b到这里就证明完了)**。但其实在这个call()方法内部调用了我们真正提交Runable任务的run()方法,并返回了null值,相当于没有返回值
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
}
至此,本文就结束了,总之逻辑有点儿绕,但只要弄清楚前面提到的类和接口的关系,后面的逻辑就很清楚了