博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java多线程之Future和FutureTask
阅读量:7122 次
发布时间:2019-06-28

本文共 7122 字,大约阅读时间需要 23 分钟。

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

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

  

public interface Callable
{ /** * 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
{ /** * 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
cancel is called, * this task should never run. If the task has already started, * then the
mayInterruptIfRunning parameter determines * whether the thread executing this task should be interrupted in * an attempt to stop the task. * *

After this method returns, subsequent calls to {

@link #isDone} will * always return true. Subsequent calls to {
@link #isCancelled} * will always return true if this method returned true. * * @param mayInterruptIfRunning true if the thread executing this * task should be interrupted; otherwise, in-progress tasks are allowed * to complete * @return false if the task could not be cancelled, * typically because it has already completed normally; * true otherwise */ boolean cancel(boolean mayInterruptIfRunning); /** * Returns true if this task was cancelled before it completed * normally. * * @return true if this task was cancelled before it completed */ boolean isCancelled(); /** * Returns true if this task completed. * * Completion may be due to normal termination, an exception, or * cancellation -- in all of these cases, this method will return * true. * * @return true 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 get method will return the task's result upon     * successful completion.     *     * 

* If you would like to immediately block waiting * for a task, you can use constructions of the form * result = exec.submit(aCallable).get(); * *

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 */
Future
submit(Callable
task); /** * Submits a Runnable task for execution and returns a Future * representing that task. The Future's
get 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 */
Future
submit(Runnable task, T result); /** * Submits a Runnable task for execution and returns a Future * representing that task. The Future's
get method will * return
null upon
successful 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
future = getDataFromRemoteByFuture(); //do something.... List data = future.get();

 

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

private Future
getDataFromRemoteByFuture() { return threadPool.submit(new Callable
() { @Override public List call() throws Exception { return getDataFromRemote(); } }); }

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

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

    

FutureTask
futureTask = new FutureTask
(new Callable
() { @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的任务调度。

    

转载于:https://www.cnblogs.com/hupengcool/p/3760196.html

你可能感兴趣的文章
[应用模板]简洁优雅网站
查看>>
VCL篇:DevExpress v16.1新功能介绍
查看>>
iOS 之 CFBridgingRelease
查看>>
变量的存储类型
查看>>
使用AVAudioPlayer出现的问题
查看>>
封装性
查看>>
如何在适合OpenCart系统运行的美国服务器空间建立SMTP服务
查看>>
JAVA中int、String的类型转换
查看>>
MongoDB Could not find host matching read preference { mode: \"primary\" } for set repl_shard1
查看>>
SOAP webserivce 和 RESTful webservice 对比及区别
查看>>
系统操作日志设计
查看>>
spring boot 资料
查看>>
iOS5系统API和5个开源库的JSON解析速度测试
查看>>
iOS入门实例文章目录
查看>>
android Activity.java 源码
查看>>
Override VK_TTALK & VK_TEND
查看>>
mysql使用MRG_MyISAM(MERGE)实现水平分表
查看>>
Kurento应用安全
查看>>
移动开发(IOS) – Objective-C-01-概述
查看>>
iOS与JS交互02
查看>>