`
milagro
  • 浏览: 13898 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Callable、Future和CompletionService

阅读更多

在整理执行器Executor之前,需要提到这样几个类/接口,这些类在使用执行器实现并发开发的时候是比较有用的,他们就是Callable、Future和CompletionService。

0. Callable

在最开始整理Java多线程并发的文章时就提到过了,Runnable是在JDK1.0中就有的。我们再来回头看下java.lang.Runnable:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface Runnable {  
  2.    public abstract void run();  
  3. }  

 

可以看到其只有一个public void修饰的run()方法,注意是返回类型为void方法,这就意味着对这个方法的调用不会有是没有返回结果的,但很多场景一个任务完成执行,我们是需要知道它的结果的。为了弥补这个不足, 从JDK1.5开始,在java.util.concurrent包中就有了Callable这个接口。

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface Callable<V> {  
  2.     V call() throws Exception;  
  3. }  

 

注意到,其中call()方法除了有返回结果以外,比起run()还有异常抛出,这个使用时是要注意的。

在JavaSE5之后,执行器Executor是JDK提供给我们的良好工具,在ExecutorService中也有了支持Callable的submit()方法,那么对于其call()的执行结果我们如何来取呢,这就要提到另一个类——java.util.concurrent.Future。

1. Future

此前整理Java并发文章,在写任务终止的时候就提到过这个接口,我们来回顾一下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface Future<V> {  
  2.     boolean cancel(boolean mayInterruptIfRunning);  
  3.     boolean isCancelled();  
  4.     boolean isDone();  
  5.     V get() throws InterruptedException, ExecutionException;  
  6.     V get(long timeout, TimeUnit unit)  
  7.         throws InterruptedException, ExecutionException, TimeoutException;  
  8. }  

 

接口中列出了5个方法,分两大方面。除了对任务终止处理以外,Future的作用就是通过get()方法拿到特定类型的结果。

2. FutureTask类与RunnableFuture接口

和Future接口一起,在java.util.concurrent包中,FutureTask是其具体的实现类。而在JDK1.6中,又引入了RunnableFuture这样一个概念:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface RunnableFuture extends Runnable, Future {  
  2.     void run();  
  3. }  

 

乍一看,其实并没有什么,不过是把Runnable和Future两个接口捏到一起了。实际上,这个接口用意应该是这样的,将需要run()的任务和结果结合在一起,执行了run()能够保证结果被设置从而可以获取到。

在ExecutorService中,submit()方法会有很多重载实现,有的用Runnable参数,有的用Callable参数。而对于submit()方法本身的实际操作,就是:

  • 执行任务
  • 返回Future对象

在实现中,AbstractExecutorService的submit()方法无论传入的是Callable还是Runnable,都会调用newTaskFor()将其转变为一个RunnableFuture对象,这个对象既会被用来调用Executor的execute()方法,也会作为Future结果返回。

JDK1.6之后,FutureTask也就成为了RunnableFuture的一个实现,当然也还是Future的实现类。我们再来简单看下它的实现。

前面文章提到过AbstractQueuedSynchronizer类(AQS)的应用,实际上FutureTask中也有一个名为Sync而且继承于AQS的内部类。在FutureTask的实现中,每个任务都有执行状态,其巧妙地运用了AQS提供的state属性和protected方法,保证了对Future结果获取线程的阻塞和唤醒。

3. CompleteService

最后稍微提一下CompleteService接口,这个接口是为了方便多个任务执行时,可以方便得获取到执行任务的Future结果。接口内容如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface CompletionService<V> {  
  2.     Future<V> submit(Callable<V> task);  
  3.     Future<V> submit(Runnable task, V result);  
  4.     Future<V> take() throws InterruptedException;  
  5.     Future<V> poll();  
  6.     Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;  
  7. }  

 

同样,也是五个方法,分为两大方面。一个是对Callable和Runnable类型参数的任务提交,另一方面则是尝试对结果以不同的方式进行获取,take()方法一般是阻塞式的获取,后两者则更灵活。

通常来讲,CompleteService是要和Executor结合在一起使用的,这在后面讲Executor的时候还会详细讲到。

分享到:
评论

相关推荐

    Java利用future及时获取多线程运行结果

    使用Future和CompletionService可以实现异步计算和非阻塞的任务调用,并可以实时获取多线程运行结果。这对于Java编程中的多线程编程非常重要。 知识点: 1. 使用Future接口来实现异步计算和非阻塞的任务调用。 2. ...

    浅谈Java多线程处理中Future的妙用(附源码)

    "浅谈Java多线程处理中Future的妙用" 在Java多线程处理中,Future是一个非常重要的概念,它可以帮助我们更好地...使用Future和CompletionService可以帮助我们更好地处理并发任务,并且可以提高系统的性能和可靠性。

    通过多线程任务处理大批量耗时业务并返回结果

    3. `submit()`方法:用于向`ExecutorService`提交任务,如果任务是`Callable`,它将返回一个`Future`,可以通过`Future.get()`来获取任务结果。 4. `CompletionService`:可能是`ExecutorCompletionService`,它...

    32 请按到场顺序发言—Completion Service详解.pdf

    `ExecutorService`允许我们提交任务(通常是`Runnable`或`Callable`)到线程池中进行异步执行,并通过`Future`接口获取任务的返回值。然而,当有多项任务同时执行时,`ExecutorService`默认不会按照任务完成的顺序...

    java.util.concurrent.uml.pdf

    ExecutorService是Executor的一个子接口,增加了submit方法,允许提交Callable和Runnable任务,并返回一个Future对象,表示异步计算的结果。submit方法有两种形式,一种接受Runnable参数并返回一个Future,另一种...

    java多线程异步性

    在Java中,通常通过Future和Callable接口实现异步计算,或者使用ExecutorService和CompletionService来管理和控制异步任务。 三、ExecutorService与ThreadPoolExecutor ExecutorService是Java并发框架中的核心接口...

    JAVA并发编程实践-线程执行-学习笔记

    对于那些具有数据依赖关系或者需要返回结果的任务,Java提供了Callable接口和Future接口。Callable任务可以有返回值,而Future则用于获取Callable任务的结果。这种方式使得异步计算结果的获取成为可能。 并行运行类...

    java并发(二十四)多线程结果组装

    通过`CompletionService.submit(Callable)`提交任务,然后调用`take()`或`poll()`方法来获取最先完成的任务结果,这样可以按照任务完成的顺序组装结果,无需等待所有任务完成。 另外,`CompletableFuture`是Java 8...

    Executor框架使用详解

    `FutureTask`类实现了`Future`和`Runnable`,可以用来包装`Callable`任务并提交给`ExecutorService`。 标签中提到的“源码”意味着深入理解Executor框架的实现原理是重要的。例如,理解`ThreadPoolExecutor`如何...

    java多线程并发编程例子

    `TestCompletionService.java`可能展示了如何结合`ExecutorService`和`Future`来使用`CompletionService`。 4. **ScheduledThreadPoolExecutor**:这个类扩展了`ThreadPoolExecutor`,增加了定时和周期性执行任务的...

    02-4(马士兵)-多线程并发

    5. Future和Callable接口:Callable接口允许创建返回值的任务,而Future接口代表Callable任务的结果,并提供检查任务是否完成、获取结果、取消任务等方法。 6. Atomic类:提供了一组原子操作的类,如AtomicInteger...

    多线程、JVM复习&面试&强化训练100题

    Executor框架包括了Executor、ExecutorService、CompletionService、Future、Callable等接口和类。Executors则是Executor框架的一个工具类,用于创建不同类型的线程池。 在实际应用中,线程池的使用场景广泛,例如...

    JAVA高质量并发详解,多线程并发深入讲解

    对比`Runnable`和`Callable`接口的不同之处,特别是在返回值和异常处理方面的差异。 - **第8章:ThreadLocal的使用** 讨论如何使用`ThreadLocal`在每个线程中存储独立的数据副本,从而避免线程间的数据竞争。 - *...

    JAVA核心知识点整理、面试必备

    除了多线程,还包括线程池的使用(ExecutorService,ThreadPoolExecutor),并发工具类(如Future, Callable, CompletionService),以及并发设计模式的应用。 7. **Spring框架**: 了解依赖注入、AOP(面向切面...

    个人总结的深入java多线程开发

    9)已完成任务队列CompletionService 36 10)计时器CountDownLatch 37 11)周期性同步工具CyclicBarrier 38 12)异步计算的结果Future 40 13)安排线程池ScheduledExecutorService 40 五多线程面试题 41 六其他主题 41 1)...

    精通并发与Netty(共92讲)百度网盘地址.txt

    - **CompletionService**:结合Executor和Future,提供了一种等待多个任务完成的解决方案。 #### 2.2 Java内存模型 - **volatile关键字**:确保了变量的可见性和禁止指令重排。 - **原子变量**:如AtomicInteger等...

    MultiThreadExample:多线程示例 Java

    此外,Java并发API(java.util.concurrent)提供了一些高级工具,如ExecutorService、Future、Callable和CompletionService,它们简化了多线程编程并提高了性能。 - ExecutorService允许我们创建线程池,管理和控制...

    18.【线程池、Lambda表达式】_java线程_lambda线程池_meantbs3_

    同时,`Future`和`Callable`接口也可以与Lambda表达式结合,用于处理有返回结果的任务。通过这种方式,我们不仅可以灵活控制线程的并发执行,还可以高效地管理任务的生命周期和结果。 总结来说,Java线程池通过复用...

    Java并发编程实战

    6.3.2 携带结果的任务Callable与Future 6.3.3 示例:使用Future实现页面渲染器 6.3.4 在异构任务并行化中存在的局限 6.3.5 CompletionService:Executor与BlockingQueue 6.3.6 示例:使用CompletionService实现...

Global site tag (gtag.js) - Google Analytics