Executor框架使用Runnable 作为其基本的任务表示形式。Runnable是一种有局限性的抽象,然后可以写入日志,或者共享的数据结构,但是他不能返回一个值。

  许多任务实际上都是存在延迟计算的:执行数据库查询,从网络上获取资源,或者某个复杂耗时的计算。对于这种任务,Callable是一个更好的抽象,他能返回一个值,并可能抛出一个异常。Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务。

  

public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
public interface Future<V> {

    /**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return <tt>true</tt>. Subsequent calls to {@link #isCancelled}
* will always return <tt>true</tt> if this method returned <tt>true</tt>.
*
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return <tt>false</tt> if the task could not be cancelled,
* typically because it has already completed normally;
* <tt>true</tt> otherwise
*/
boolean cancel(boolean mayInterruptIfRunning); /**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally.
*
* @return <tt>true</tt> if this task was cancelled before it completed
*/
boolean isCancelled(); /**
* Returns <tt>true</tt> if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* <tt>true</tt>.
*
* @return <tt>true</tt> if this task completed
*/
boolean isDone(); /**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
*/
V get() throws InterruptedException, ExecutionException; /**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws TimeoutException if the wait timed out
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}

  可以通过多种方法来创建一个Future来描述任务。ExecutorService中的submit方法接受一个Runnable或者Callable,然后返回一个Future来获得任务的执行结果或者取消任务。

    /**
* Submits a value-returning task for execution and returns a
* Future representing the pending results of the task. The
* Future's <tt>get</tt> method will return the task's result upon
* successful completion.
*
* <p>
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
* <tt>result = exec.submit(aCallable).get();</tt>
*
* <p> Note: The {@link Executors} class includes a set of methods
* that can convert some other common closure-like objects,
* for example, {@link java.security.PrivilegedAction} to
* {@link Callable} form so they can be submitted.
*
* @param task the task to submit
* @return a Future representing pending completion of the task
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if the task is null
*/
<T> Future<T> submit(Callable<T> task); /**
* Submits a Runnable task for execution and returns a Future
* representing that task. The Future's <tt>get</tt> method will
* return the given result upon successful completion.
*
* @param task the task to submit
* @param result the result to return
* @return a Future representing pending completion of the task
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if the task is null
*/
<T> Future<T> submit(Runnable task, T result); /**
* Submits a Runnable task for execution and returns a Future
* representing that task. The Future's <tt>get</tt> method will
* return <tt>null</tt> upon <em>successful</em> completion.
*
* @param task the task to submit
* @return a Future representing pending completion of the task
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if the task is null
*/
Future<?> submit(Runnable task);

  另外ThreadPoolExecutor中的newTaskFor(Callable<T> task) 可以返回一个FutureTask。

假设我们通过一个方法从远程获取一些计算结果,假设方法是  List getDataFromRemote(),如果采用同步的方法,代码大概是 List data = getDataFromRemote(),我们将一直等待getDataFromRemote返回,然后才能继续后面的工作,这个函数是从远程获取计算结果的,如果需要很长时间,后面的代码又和这个数据没有什么关系的话,阻塞在那里就会浪费很多时间。我们有什么办法可以改进呢???

能够想到的办法是调用函数后,立即返回,然后继续执行,等需要用数据的时候,再取或者等待这个数据。具体实现有两种方式,一个是用Future,另一个是回调。

        Future<List> future = getDataFromRemoteByFuture();
//do something....
List data = future.get();

  可以看到我们返回的是一个Future对象,然后接着自己的处理后面通过future.get()来获得我们想要的值。也就是说在执行getDataFromRemoteByFuture的时候,就已经启动了对远程计算结果的获取,同时自己的线程还继续执行不阻塞。知道获取时候再拿数据就可以。看一下getDataFromRemoteByFuture的实现:

private Future<List> getDataFromRemoteByFuture() {

        return threadPool.submit(new Callable<List>() {
@Override
public List call() throws Exception {
return getDataFromRemote();
}
});
}

我们在这个方法中调用getDataFromRemote方法,并且用到了线程池。把任务加入线程池之后,理解返回Future对象。Future的get方法,还可以传入一个超时参数,用来设置等待时间,不会一直等下去。

也可以利用FutureTask来获取结果:

    

    FutureTask<List> futureTask = new FutureTask<List>(new Callable<List>() {
@Override
public List call() throws Exception {
return getDataFromRemote();
}
}); threadPool.submit(futureTask); futureTask.get();

FutureTask是一个具体的实现类,ThreadPoolExecutor的submit方法返回的就是一个Future的实现,这个实现就是FutureTask的一个具体实例,FutureTask帮助实现了具体的任务执行,以及和Future接口中的get方法的关联。FutureTask除了帮助ThreadPool很好的实现了对加入线程池任务的Future支持外,也为我们提供了很大的便利,使得我们自己也可以实现支持Future的任务调度。

java多线程之Future和FutureTask的更多相关文章

  1. Java多线程之Future与FutureTask

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561154.html  一:Future 在使用实现Callable创建线程时,call()方法是有返回值的. ...

  2. JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止

    JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 背景 当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境 ...

  3. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

  4. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

  5. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

  6. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  7. Java多线程之Runnable与Thread

    Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...

  8. java多线程之wait和notify协作,生产者和消费者

    这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...

  9. java多线程之Callable、Future和FutureTask

    Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...

随机推荐

  1. 通过ajax获得json数据后格式的转换

    在有些情况下获取到的json数据可能是string类型的,需要把其格式化为json对象才方便解析. a)原生js通过ajax获取到的json 此时返回的数据默认是string型的,所以需要用eval( ...

  2. 大数据平台搭建(hadoop+spark)

    大数据平台搭建(hadoop+spark) 一.基本信息 1. 服务器基本信息 主机名 ip地址 安装服务 spark-master 172.16.200.81 jdk.hadoop.spark.sc ...

  3. win7和linux下的文件共享

    在vmware虚拟机下安装linux系统,如果自个电脑的win7设置成自动获取IP的话,每次使用FTP文件传输服务器都要检查win7和linux系统的IP是否处于同一网段,如果不是还要手动设置.再有一 ...

  4. 用java写一个web服务器

    一.超文本传输协议 Web服务器和浏览器通过HTTP协议在Internet上发送和接收消息.HTTP协议是一种请求-应答式的协议——客户端发送一个请求,服务器返回该请求的应答.HTTP协议使用可靠的T ...

  5. nutch-2.2.1 hadoop-1.2.1 hbase-0.92.1 集群部署

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

  6. PL/pgSQL学习笔记之八

    http://www.postgresql.org/docs/9.1/static/plpgsql-declarations.html 另外一种声明 PL/pgSQL 函数的方法是使用 returns ...

  7. SQL扫描并执行文件夹里的sql脚本

    场景:项目数据库操作全部使用存储过程实现.每天都会有很多存储过程更新/增加,人工对测试环境中存储过程更新,会有一定概率出现遗漏,也麻烦!所以,需要一个工具将文件夹中所有存         储过程执行一 ...

  8. 【M29】引用计数

    1.引用计数这项技术,是为了让等值对象对象共享同一实体.此技术的发展有两个动机:a.记录堆上分配的对象,是垃圾回收机制的简单原理:b.节省内存,多个对象具有相同的值,存储多次很笨.速度更快,等值对象避 ...

  9. ListView的自动循环滚动显示

    最近项目里需要做评价内容的循环滚动显示,一开始想到的就是定时器.后来查了资料才知道ListView里面有个函数smoothScrollToPosition(position),瞬间觉得简单了很多.首先 ...

  10. [MEAN Stack] First API -- 1. with Node.js, Express and MongoDB

    Learn how to import data into your MongoDB and then use Express to serve a simple Node.js API. Impor ...