FutureTask
类的结构:
demo代码:
上述代码中通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
api:
//取消任务的执行。参数指定是 否立即中断任务执行,或者等等任务结束boolean cancel (boolean mayInterruptIfRunning)//任务是否已经取消,任务正常完成前将其取消,则返回 trueboolean isCancelled ()//任务是否已经完成。需要注意的是如果任务正常终止、异常或 取消,都将返回trueboolean isDone ()//等待任务执行结 束,然后获得V类型的结果。InterruptedException 线程被中断异常,// ExecutionException任务执行异常,如果任务被取消,还会抛出 CancellationExceptionV get () throws InterruptedException, ExecutionException//同上面的get功能一样,多了设置超时时间。 参数timeout指定超时时间,uint指定时间的单位//如果计算超时,将抛出TimeoutExceptionV get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
备注:throws InterruptedException的方法一般都会堵塞
缺点:
并发执行多任务时:因为Future提供的get()方法是阻塞的。如果第一个任务执行时间很长,主线程就会堵塞在第一个任务上。在某些业务场景中,比如向不同电商平台询价,并保存价格,如果其中一个平台询价时间长,不希望去影响这个任务影响其他任务的执行,并且部分平台查询失败的情况也不影响业务运行
就有了CompletionService
CompletionService
CompletionService可以实现先执行完的任务先取结果,不再依赖任务顺序。
demo:
//创建线程池ExecutorService executor=Executors.newFixedThreadPool(10);//创建CompletionServiceCompletionService<Integer> cs = new ExecutorCompletionService<>(executor);//异步向电商S1询价cs.submit(()‐>getPriceByS1());//异步向电商S2询价cs.submit(()‐>getPriceByS2());//异步向电商S3询价cs.submit(()‐>getPriceByS3());//将询价结果异步保存到数据库for (int i= 0; i< 3; i++) {Integer r = cs.take().get();executor.execute(()‐>save(r));}
实现原理
内部有一个先进先出的阻塞队列,用于保存已经执行完成的Future,通过调用它的 take方法或poll方法可以获取到一个已经执行完成的Future,进而通过调用Future接口实现类 的get方法获取最终的结果
所以当需要批量提交异步任务的时候优先考虑CompletionService
api:

