execute(Runnable command)接口是无返回值的,与之相对应的是一个有返回值的接口Future submit(Callable task),这点在前面已经提到。
Callable也就是一个有返回值的Runnable,其定义如下所示。
使用方式如下:
submit(Callable task)并不是在 ThreadPoolExecutor 里面直接实现的,而是实现在其父类AbstractExecutorService中,源码如下:
从这段代码中可以看出,Callable其实是用Runnable实现的。在submit内部,把Callable通过FutureTask这个Adapter转化成Runnable,然后通过execute执行。如图6-5所示为Callable被转换成Runnable示意图。
FutureTask是一个Adapter对象。一方面,它实现了Runnable接口,也实现了Future接口;另一方面,它的内部包含了一个Callable对象,从而实现了把Callable转换成Runnable。
如图6-6所示,一方面,线程池内部的线程在执行RunTask的run()方法;另一方面,外部多个线程又在调用get()方法,等着返回结果,因此这个地方需要一个阻塞—通知机制。
在JDK 6中借用AQS的功能来实现阻塞—唤醒。但自JDK 7开始,既没有借用AQS的功能,也没有使用Condition的await()/notify()机制,而是直接基于CAS state变量+park/unpark()来实现阻塞—唤醒机制。由于这个原理在上文讲AQS和Condition的时候已反复提及,此处就不再对awaitDone()进一步展开分析了。