通过ExecutorService.submit()方法提交的任务,可以获取任务执行完的返回值。
在实际业务场景中,Future和Callable基本是成对出现的,Callable负责产生结果,Future负责获取结果。
1、Callable接口类似于Runnable,只是Runnable没有返回值。
2、Callable任务除了返回正常结果之外,如果发生异常,该异常也会被返回,即Future可以拿到异步执行任务各种结果;
3、Future.get方法会导致主线程阻塞,直到Callable任务执行完成;
1、Callable接口类似于Runnable,只是Runnable没有返回值。
2、Callable任务除了返回正常结果之外,如果发生异常,该异常也会被返回,即Future可以拿到异步执行任务各种结果;
3、Future.get方法会导致主线程阻塞,直到Callable任务执行完成;
submit实现
FutureTask
1、FutureTask在不同阶段拥有不同的状态state,初始化为NEW;
2、FutureTask类实现了Runnable接口,这样就可以通过Executor.execute方法提交FutureTask到线程池中等待被执行,最终执行的是FutureTask的run方法;
FutureTask.get实现
内部通过awaitDone方法对主线程进行阻塞,具体实现如下:
1、如果主线程被中断,则抛出中断异常;
2、判断FutureTask当前的state,如果大于COMPLETING,说明任务已经执行完成,则直接返回;
3、如果当前state等于COMPLETING,说明任务已经执行完,这时主线程只需通过yield方法让出cpu资源,等待state变成NORMAL;
4、通过WaitNode类封装当前线程,并通过UNSAFE添加到waiters链表;
5、最终通过LockSupport的park或parkNanos挂起线程;
2、判断FutureTask当前的state,如果大于COMPLETING,说明任务已经执行完成,则直接返回;
3、如果当前state等于COMPLETING,说明任务已经执行完,这时主线程只需通过yield方法让出cpu资源,等待state变成NORMAL;
4、通过WaitNode类封装当前线程,并通过UNSAFE添加到waiters链表;
5、最终通过LockSupport的park或parkNanos挂起线程;
FutureTask.run实现
1、通过执行Callable任务的call方法;
2、如果call执行成功,则通过set方法保存结果;
3、如果call执行有异常,则通过setException保存异常;
set
setException
set和setException方法中,都会通过UnSAFE修改FutureTask的状态,并执行finishCompletion方法通知主线程任务已经执行完成;
finishCompletion
1、执行FutureTask类的get方法时,会把主线程封装成WaitNode节点并保存在waiters链表中;
2、FutureTask任务执行完成后,通过UNSAFE设置waiters的值,并通过LockSupport类unpark方法唤醒主线程;
2、FutureTask任务执行完成后,通过UNSAFE设置waiters的值,并通过LockSupport类unpark方法唤醒主线程;
最后来一个Future、Callable、FutureTask调用区别实例
class Task implements Callable<String> {
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(8);
return Thread.currentThread().getName()+" Callable is call";
}
}
public void show() {
Task mTask=new Task();
//线程池调用Future和Callable
ExecutorService executorService = Executors.newFixedThreadPool(4);
Future<String> future = executorService.submit(mTask);
System.out.println("ExecutorSevice and Future and Callable is doing");
try {
String resultOne = future.get();
System.out.println("resultOne值为:" + resultOne);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//线程池调用FutureTask
FutureTask<String> futureTask=new FutureTask<String>(mTask);
executorService.submit(futureTask);
System.out.println("ExecutorSevice and FutureTask is doing");
try {
String resultTwo = futureTask.get();
System.out.println("resultTwo值为:" + resultTwo);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//Thread调用FutureTask
FutureTask<String> futureTaskTwo=new FutureTask<String>(mTask);
new Thread(futureTaskTwo).start();
System.out.println("Thread and FutureTask is doing");
try {
String resultThree = futureTaskTwo.get();
System.out.println("resultThree值为:" + resultThree);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
日志打印如下: