Callable和Future

简介:

原文链接  译文链接  译者:Greenster  校对:沈义扬
Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理。Thread类、Runnable接口和Java内存管理模型使得多线程编程简单直接。但正如之前提到过的,Thread类和Runnable接口都不允许声明检查型异常,也不能定义返回值。没有返回值这点稍微有点麻烦。

 不能声明抛出检查型异常则更麻烦一些。public void run()方法契约意味着你必须捕获并处理检查型异常。即使你小心地保存了异常信息(译者注:在捕获异常时)以便稍后检查,但也不能保证这个类(译者注:Runnable对象)的所有使用者都读取异常信息。你也可以修改Runnable实现的getter,让它们都能抛出任务执行中的异常。但这种方法除了繁琐也不是十分安全可靠,你不能强迫使用者调用这些方法,程序员很可能会调用join()方法等待线程结束然后就不管了。

但是现在不用担心了,以上的问题终于在1.5中解决了。Callable接口和Future接口的引入以及他们对线程池的支持优雅地解决了这两个问题。

Callable

Callable接口定义了方法public T call() throws Exception。我们可以在Callable实现中声明强类型的返回值,甚至是抛出异常。尽管在Executors类中已经有一些方法可以将Runnable对象转换为Callable对象,你最好还是仔细复审现有的Runnable实现或Thread的子类。为什么还要这样做?主要是为了检查和清除因为Runnable无法抛出检查型异常而采用的变通方案。同时,你可能希望利用call()方法直接返回结果的能力,以省去读取值时的类型转换。

Future

下面就将线程池和Callable接口相结合,看能发生怎样的效应。Future是Java 1.5中引入的接口,当你提交一个Callable对象给线程池时,将得到一个Future对象,并且它和你传入的Callable有相同的结果类型声明。这个对象取代了Java 1.5之前直接操作具体Thread实例的做法。过去你不得不用Thread.join()或者Thread.join(long millis)等待任务完成,而现在你可以像下面的例子那样做。


01 public class ServerAcceptingRequestsVerifier implements Callable {
02     /**
03      * @return Boolean.TRUE is server is accepting requests
04      * Boolean.FALSE otherwise
05      */
06     public Boolean call() throws Exception {
07         Boolean isAcceptingRequests = null;
08         ... ask server about taking requests here
09         return isAcceptingRequests;
10     }
11 }
12 public Boolean isServerTakingRequests(String server)
13             throws UnresponsiveException, InterruptedException {
14     ServerAcceptingRequestsVerifier acceptingRequestsVerifier =
15         new ServerAcceptingRequestsVerifier();
16     Future future =
17         THREAD_POOL.submit(acceptingRequestsVerifier);
18     try {
19         Boolean isAcceptingRequests = future.get();
20         //waits for the thread to complete, even if it hasn't started
21         return isAcceptingRequests;
22     } catch (ExecutionException e) {
23         throw new UnresponsiveException(e.getCause());
24     }
25  
26 }

如果要限制等待任务结束的时间,也可以添加一个捕获TimeoutException的catch子句


01 try {
02     Boolean isAcceptingRequests = future.get(5, TimeUnit.SECONDS);
03     //this waits for 5 seconds, throwing TimeoutException if not done
04     return isAcceptingRequests;
05 } catch (TimeoutException e) {
06     LOGGER.warn("Timed out waiting for server check thread." +
07         "We'll try to interrupt it.");
08     future.cancel(true);
09     return Boolean.FALSE;
10 } catch (ExecutionException e) {
11     throw new UnresponsiveException(e.getCause());
12 }
目录
相关文章
|
3月前
|
并行计算 Java 大数据
Callable和Future
Callable和Future
|
2月前
|
并行计算 Java API
|
6月前
|
C++
C++Future简单的使用
C++Future简单的使用
53 0
|
消息中间件 Java 中间件
Future and CompletableFuture
Future代表异步执行的结果,也就是说异步执行完毕后,结果保存在Future里, 我们在使用线程池submit()时需要传入Callable接口,线程池的返回值为一个Future,而Future则保存了执行的结果 ,可通过Future的get()方法取出结果,如果线程池使用的是execute(),则传入的是Runnable接口 无返回值。
71 0
|
Java
Future和Callable学习
通常使用线程池+Runnable的时候,会发现Runnable不能返回值,也就执行的结果情况,同时对于出现异常,我们获取异常信息,进行相应的处理。如果需要返回结果,同时需要进一步加工的时候,就可以考虑使用Future+Callable了。同时接口Future的默认实现是FutureTask,因此对于其实现get()方法,会有一个问题,就是如果前面的任务一旦执行的时间耗时较长的时候,就会出现一直阻塞的状态,此时就会出现排队等待的状态,大大影响其性能。适用场景:当一个线程需要等待另一个线程把某个任务执行完成后它才能继续执行,此时可以使用FutureTask。因为FutureTask基于AQS实现,
94 0
Future和Callable学习
|
Java
Java多线程 Callable和Future
Java多线程 Callable和Future
129 0
Java多线程 Callable和Future
|
存储
多线程 - Callable、Future 和 FutureTask 简单应用(二)
多线程 - Callable、Future 和 FutureTask 简单应用(二)
119 0
多线程 - Callable、Future 和 FutureTask 简单应用(二)
|
Java
多线程 - Callable、Future 和 FutureTask 简单应用(一)
多线程 - Callable、Future 和 FutureTask 简单应用(一)
144 0
|
Java 程序员
使用 Callable 和 Future 创建线程
使用 Callable 和 Future 创建线程
319 0