我们知道线程池通过execute方法执行提交的Runnable任务,但Runnable只是执行任务,没有返回任何信息。
【线程池原理:线程池原来是个外包公司,打工人我悟了】
若是我们想在异步执行完任务后能够拿到结果。怎么处理呢?
我们可以借助Callable来回去返回结果。线程池为我们提供了另外一种方式执行任务,即submit方法
1、为线程池提交任务
execute方法执行Runnable任务
submit方法执行Runnable或Callable任务,且能获取任务返回结果
2、流程分解
2.1、execute方法执行Runnable任务
execute方法将Runnable任务交付给线程池执行
2.2、submit方法执行Runnable或Callable任务
2.2.1、创建futureTask对象(也是Runnable对象),包含属性Callable和object;将futureTask对象引用传递给外部
public class FutureTask<V> implements RunnableFuture<V> {
FutureTask中的状态属性(state)代表任务执行的进度。当任务执行到最终态时,代表任务执行结束。
后面调用get()方法时,判断到最终态才能获取object的值
2.2.2、若传入Runnable任务,将其转为Callable任务,赋值给Callable;
若传入Callable任务,则直接赋值给Callable
public static <T> Callable<T> callable(Runnable task, T result) {
2.2.3、futureTask作为Runnable,execute方法执行此任务(见2.1)
2.2.4、当执行futureTask时,会调用其run方法执行Callable任务
Callable任务若正常返回结果则赋值给object;
若执行异常,则将异常捕获并赋值给object
2.2.5、外部根据futureTask对象引用,调用get()方法,获取到futureTask中的object;区分是返回结果或异常进行处理
public V get() throws InterruptedException, ExecutionException {
通过get()获取结果的过程:
判断任务是否达到最终态。若达到,则根据状态将outcome值区分处理
-
若未达到
通过LockSupport.parkNanos(futureTask, nanos);挂起当前线程;
futureTask执行到最终态后会执行LockSupport.unpark(thread);重新恢复 因调用get()而挂起的线程
------The End------
如果这个办法对您有用,或者您希望持续关注,可以在wx公众号中搜索【码路无涯】,期待你的到来