future java submitall_java多线程之Future和FutureTask

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

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

public interface Callable{/*** Computes a result, or throws an exception if unable to do so.

*

*@returncomputed result

*@throwsException if unable to compute a result*/V call()throwsException;

}

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.

*

*@parammayInterruptIfRunning true if the thread executing this

* task should be interrupted; otherwise, in-progress tasks are allowed

* to complete

*@returnfalse if the task could not be cancelled,

* typically because it has already completed normally;

* true otherwise*/

boolean cancel(booleanmayInterruptIfRunning);/*** Returns true if this task was cancelled before it completed

* normally.

*

*@returntrue if this task was cancelled before it completed*/

booleanisCancelled();/*** 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.

*

*@returntrue if this task completed*/

booleanisDone();/*** Waits if necessary for the computation to complete, and then

* retrieves its result.

*

*@returnthe computed result

*@throwsCancellationException if the computation was cancelled

*@throwsExecutionException if the computation threw an

* exception

*@throwsInterruptedException if the current thread was interrupted

* while waiting*/V get()throwsInterruptedException, ExecutionException;/*** Waits if necessary for at most the given time for the computation

* to complete, and then retrieves its result, if available.

*

*@paramtimeout the maximum time to wait

*@paramunit the time unit of the timeout argument

*@returnthe computed result

*@throwsCancellationException if the computation was cancelled

*@throwsExecutionException if the computation threw an

* exception

*@throwsInterruptedException if the current thread was interrupted

* while waiting

*@throwsTimeoutException if the wait timed out*/V get(longtimeout, TimeUnit unit)throwsInterruptedException, 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 {@linkExecutors} class includes a set of methods

* that can convert some other common closure-like objects,

* for example, {@linkjava.security.PrivilegedAction} to

* {@linkCallable} form so they can be submitted.

*

*@paramtask the task to submit

*@returna Future representing pending completion of the task

*@throwsRejectedExecutionException if the task cannot be

* scheduled for execution

*@throwsNullPointerException if the task is null*/

Future submit(Callabletask);/*** 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.

*

*@paramtask the task to submit

*@paramresult the result to return

*@returna Future representing pending completion of the task

*@throwsRejectedExecutionException if the task cannot be

* scheduled for execution

*@throwsNullPointerException if the task is null*/

Futuresubmit(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.

*

*@paramtask the task to submit

*@returna Future representing pending completion of the task

*@throwsRejectedExecutionException if the task cannot be

* scheduled for execution

*@throwsNullPointerException if the task is null*/Future> submit(Runnable task);

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

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

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

Future future =getDataFromRemoteByFuture();//do something....

List data = future.get();

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

private FuturegetDataFromRemoteByFuture() {return threadPool.submit(new Callable() {

@Overridepublic List call() throwsException {returngetDataFromRemote();

}

});

}

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

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

FutureTask futureTask = new FutureTask(new Callable() {

@Overridepublic List call() throwsException {returngetDataFromRemote();

}

});

threadPool.submit(futureTask);

futureTask.get();

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值