`
Tonyguxu
  • 浏览: 281355 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【Java并发】可携带结果的任务:Callable和Future

 
阅读更多

任务

      Executor框架使用Runnable作为任务的基本抽象。Runnable确实有限的抽象,虽然能够产生一些边界效应,如记录日志文件或者将结果写入一个共享数据结构里,但是不能返回一个值或者抛出检测异常。

     很多任务会引起严重的计算延迟——执行DB查询,从网络上获取资源,复杂计算等。对于这些任务,Callable是更佳的抽象。

     Runnable和Callable描述的是抽象的计算型任务,这些任务通常是有限的:有一个明确的开始点,而且最终会结束。一个Executor执行的任务的生命周期可有四个阶段:

created --> submitted --> started --> completed.

 

Callable

 

包:java.util.concurrent
类:public interface Callable<V>
方法:V call() throws Exception

 

      Callable Task是有lifecycle的,分别为created/submitted/started/completed(创建/提交/启动/完成)。

      对于处在submitted与started间的task可以通过Future来cancel该task,对于已经started但是还没有completed的task,只能期望task能够响应interruption从而终止(Future依然调用cancel)。对于已经completed的task是无法被cancel的,此时如果调用cancel则会返回false(其实如果调用cancel返回false一般是因为该task已经completed)。


任务封装
       Executors提供了些工具方法用于将其他类型的任务(如Runnable、java.security.PrivilegedAction)封装成一个Callable。
public class Executors extends Object
//返回 Callable 对象,调用它时可运行给定的任务并返回 null。
static Callable<Object> callable(Runnable task) 
//返回 Callable 对象,调用它时可运行给定的任务并返回给定的结果。
static <T> Callable<T> callable(Runnable task, T result) 
【扩展】 Callable callable(Runnable task, T result) ——适配器设计模式的应用

适配器模式三角色:AdapteeTargetAdapter

public static Callable<Object> callable(Runnable task) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<Object>(task, null);
}
public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
}
//Adapter类:实现目标接口,持有被适配者adaptee的引用,通过构造将被适配者实例传入
static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable  task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
}
 

Future

      描述了asynchronous computation task任务的生命周期,提供了如下功能 1.获取任务的结果 2.取消任务 3.获得任务进行状态(完成还是被取消)。
public interface Future<V>

V get() throws InterruptedException,ExecutionException
V get(long timeout,TimeUnit unit)throws InterruptedException,
             ExecutionException,
             TimeoutException
boolean cancel(boolean mayInterruptIfRunning)
boolean isCancelled()
boolean isDone() 
get():如果任务已经完成,get会立即返回或者抛出异常;如果任务没有完成,get会阻塞直到它完成。
ExecutionException:


Future继承结构

 创建描述任务的Future

方式1:将Callable或者Runnable提交给executor获得Future实例。

 

ExecutorService executor = ...

Future f = executor.submit(Callable<T> task);
Future f = executor.submit(Runnable task);
Future f = executor.submit(Runnable task, T result);

方式2:使用给定的Callable或者Runnable来实例化FutureTask。

 

FutureTask

已实现的接口:Runnable、Future、RunnableFuture。

构造:可以使用FutureTask来包装Callable或Runnable对象。

 

//FutureTask一旦运行就执行给定的 Callable
FutureTask(Callable<V> callable) 
FutureTask(Runnable runnable, V result) 

要点:

1. 因为FutureTask实现了Runnable接口,可以可将FutureTask交由Executor执行,或者构造一个Thread。

2. FutureTask的计算结果从运行计算的线程传送到需要这个结果的线程(调用get的线程),并保证这种传递建立在结果的安全发布基础上。

 

代码示例:利用FutureTask、Callable、Thread对耗时任务(如查询数据库)做预处理,在需要计算结果之前就启动计算。

(代码见ConcurrentSamples/simulate.futuretask.preload)

private final FutureTask<ProductInfo> future = 
            new FutureTask<ProductInfo>(new Callable<ProductInfo>(){
                public ProductInfo call() throws DataLoadException{
                    ProductInfoLoader loader = new ProductInfoLoader();
                    return loader.load();//加载数据:查询数据库
                }
            });
    private final Thread t = new Thread(future);
    
    public void start(){
        t.start();
    }
    
    public ProductInfo load() throws DataLoadException, InterruptedException{
        try {
            return future.get();
        } catch (ExecutionException e) {
            Throwable cause = e.getCause();
            if(cause instanceof DataLoadException)
                throw (DataLoadException)cause;
            else
                throw launderThrowable(e);
        }
    }
  • 大小: 29.9 KB
分享到:
评论

相关推荐

    Java使用Callable和Future创建线程操作示例

    Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作技巧与注意事项。 首先,Java 5开始,Java提供了...

    Callable:Callable与Future在Web应用中的优化案例

    1. **任务调度**:在高并发环境下,通过Callable和Future可以实现任务的异步处理,比如在Servlet容器中,可以创建一个线程池,将耗时的操作提交到线程池,然后返回Future对象给客户端,客户端可以依据Future检查任务...

    Java中的Runnable,Callable,Future,FutureTask的比较

    Java中的Runnable、Callable、Future和FutureTask是Java多线程编程中的核心概念,它们各自扮演着不同的角色,共同协作以实现并发任务的管理和执行。 1. **Runnable**: Runnable是最基本的多线程接口,它只有一个`...

    Callable和Future.doc

    Callable 和 Future 在 Java 多线程编程中提供了更灵活的机制,特别是对于需要返回结果和处理异常的异步任务。Callable 通过 `call()` 方法返回结果和抛出异常,而 Future 则提供了管理和获取这些结果的手段。结合 ...

    java并发包之Callable和Future

    `Callable`和`Future`的组合是Java并发包中一个强大的工具,它弥补了`Runnable`接口的不足,使得异步编程可以获取到返回值并处理异常。同时,`ExecutorService`作为线程池的实现,为并发编程提供了一种优雅的解决...

    java并发编程实战源码,java并发编程实战pdf,Java

    8. **Future与Callable接口**:这些接口允许我们异步计算结果,并能够获取任务的执行状态。 9. ** Fork/Join框架**:这是一种并行计算模型,适用于那些可以拆分为子任务并进行并行处理的问题。 10. **并发模式**:...

    JAVA并发编程艺术pdf版

    - **Future和Callable**:Future接口表示异步计算的结果,Callable接口用于定义计算任务。 5. **并发集合**: - **线程安全的集合**:如Vector、ConcurrentHashMap和CopyOnWriteArrayList等,它们在内部实现了...

    Java多线程Callable和Future接口区别

    Java多线程Callable和Future接口是Java语言中两个非常重要的接口,它们都是Java多线程编程中使用的接口,用于描述异步计算的结果。在JavaSE5中引入的Callable是一个具有类型参数的范型,他的类型参数方法表示为方法...

    (PDF带目录)《Java 并发编程实战》,java并发实战,并发

    4. **并发工具类**:`java.util.concurrent`包还包含一系列并发工具类,如`ExecutorService`、`Future`、`Callable`等,它们简化了任务的提交、管理和结果获取,使并发编程更加灵活和高效。 5. **原子变量**:Java...

    14个Java线程并发面试题和答案..pdf

    答案:Callable是指一个可以返回结果的异步任务,Future是指异步任务的结果对象。 知识点:Callable的定义、异步任务、Future的定义、结果对象。 14. 问题:如何使用Callable和Future? 答案:可以使用...

    JAVA中Callable的使用

    在Java编程语言中,Callable接口是用于创建...通过结合ExecutorService和Future,我们可以方便地管理这些任务的执行,获取结果并处理可能出现的异常。熟练掌握Callable的使用对于编写高效、健壮的并发程序至关重要。

    Java 并发编程实战.pdf

    - **Java并发机制**:Java提供了丰富的并发机制来支持多线程程序的编写,包括但不限于`Thread`类、`Runnable`接口、`Callable`接口以及`Executor`框架等。 - **锁机制**:Java中的锁机制主要包括synchronized关键字...

    Android(Java)之多线程结果返回——Future 、FutureTask、Callable、Runnable

    `Future`、`FutureTask`、`Callable`和`Runnable`是Java并发编程中的核心接口和类,它们在Android开发中同样有着广泛的应用。下面将详细介绍这些概念以及它们如何协同工作。 1. `Runnable`: 这是Java中最基础的多...

    Java并发编程Callable与Future的应用实例代码

    Java并发编程Callable与Future的应用实例代码 在Java并发编程中,Callable与Future是两个非常重要的概念,它们通常结合使用来实现异步编程。在本文中,我们将详细介绍Callable与Future的应用实例代码,并探究它们在...

    java自定义任务类定时执行任务示例 callable和future接口使用方法

    在Java多线程编程中,`Callable`接口和`Future`接口是两个重要的组件,它们提供了比`Runnable`接口更强大的功能,尤其是在处理异步计算和结果获取时。本文将详细介绍这两个接口以及如何使用它们来创建自定义任务类以...

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

    在Java中,我们可以通过`ExecutorService`和`Future`来管理多线程任务,并获取它们的执行结果。`ExecutorService`是`java.util.concurrent`包中的一个接口,用于管理和控制线程的生命周期,如启动线程、关闭线程池等...

    java并发编程内部分享PPT

    最后,Java并发编程还涉及到Future和Callable接口,它们用于异步计算和获取结果。Executor框架中的FutureTask类结合了Future和Runnable,可以在任务完成后获取结果。 总的来说,这份“java并发编程内部分享PPT”...

    Java并发工具包

    FutureTask是一个实现了Runnable和Future接口的类,可以将Callable任务包装为一个可执行的任务。它可以作为ExecutorService提交的任务,并通过Future接口获取结果。 七、ThreadLocal ThreadLocal为每个线程提供了一...

Global site tag (gtag.js) - Google Analytics