我通过《回到Future》这个工作主题开始写一系列的关于探讨编程语言的Futrure概念的文章。Futrues是非常重要的抽象,甚至随着异步,事件驱动,并行和扩展系统的发展显得更加重要。在第一篇文章中,我们会讨论最基本的java.util.concurrent.Future 接口。 接下来我们会跳到其他的框架,库,甚至是语言。 Future是有限制的,但是有必要去理解future的部分。
成都创新互联主要从事网页设计、PC网站建设(电脑版网站建设)、wap网站建设(手机版网站建设)、成都响应式网站建设、程序开发、网站优化、微网站、小程序开发等,凭借多年来在互联网的打拼,我们在互联网网站建设行业积累了丰富的网站设计、做网站、网站设计、网络营销经验,集策划、开发、设计、营销、管理等多方位专业化运作于一体。
在一个单线程应用中,当你调用一个方法只有计算结束才会返回结果( IOUtils.toString() comes from Apache Commons IO ):
- public String downloadContents(URL url) throws IOException {
- try(InputStream input = url.openStream()) {
- return IOUtils.toString(input, StandardCharsets.UTF_8);
- }
- }
- //...
- final Future
contents = downloadContents(new URL("http://www.example.com"));
downloadContents() 看上去是无害的, 但是它需要任意长的时间来完成。同时,为了减少延迟,在等待结果的期间,你可能需要同时独立的处理其它的工作。以前你可能会启动一个新的线程 或者等待结果(共享内存,锁,糟糕的 wait()/notify()对).
通过 Future
- public static Future
startDownloading(URL url) { - //...
- }
- final Future
contentsFuture = startDownloading(new URL("http://www.example.com")); - //other computation
- final String contents = contentsFuture.get();
我们马上会实现 startDownloading(), startDownloading()不会被阻塞,而是等待外部的站点回应,你理解这一原则是很重要的。 相反,如果它快速返回了,返回一个轻量级的Future
Future.get()是最重要的方法。它阻塞和等待直到承诺的结果是可用状态, 因此如果我们确实需要这个字符串,就调用get() 方法然后等待。 还有一个接受超时参数的重载版本,如果哪里出现问题你就不用一直等待下去,超过设定时间就会抛出 TimeoutException。
在某些情况下,你可能想不停地偷偷看看Future是否可用了。这可以通过isDone()来完成。想象一个情景,你的用户等待某些异步的计算,你想让他知道这种情况, 同时去做一些其它的计算:
- final Future
contentsFuture = startDownloading(new URL("http://www.example.com")); - while (!contentsFuture.isDone()) {
- askUserToWait();
- doSomeComputationInTheMeantime();
- }
- contentsFuture.get();
最后Future.get()调用的内容会保证马上返回,不会被阻塞,因为Future.isDone() 返回了true。如果你遵循这个模式,就不会忙于每秒百万次的交替等待和调用isDone()。
取消futrues是最后一个我们还没有覆盖到的。想象你启动了异步的工作并且你只能等待一些时间, 如果2秒钟后,我们放弃,或者把错误传递出去,或者采用临时方案解决它。然而,你是一个好市民,你应该告诉这个future对象:我不需要你了,你别管了。 那么你可以通过停止过时的任务,来节约资源。语法很简单:
- contentsFuture.cancel(true); //meh...
我们都喜欢隐藏的,布尔类型的参数,对吗?取消可以通过两种方式来实现:在任务启动前通过传递false参数来取消,前提是当Future表达的结果计算开始之前。一旦Callable.call()已经运行到一半,那么我们想让它结束,如果我们传递true,那么Future.call()就会具有侵入性,试图打断正在运行的工作。你觉得这样好吗?现象那些抛出InterruptedException这个声名狼藉的异常的方法,如Thread.sleep(), Object.wait(),Condition.await(),等,甚至包括Future.get(). 如果你被阻塞在这种方法并且有人决定取消你的调用,他们会毫无疑问的抛出InterruptionException,并发出有人要打断当前运行的任务。
因此我们现在明白了Future是什么--- 一个占位符,你可以在未来得到目标对象。就像对于一辆车,还没有制造出来的钥匙。但是你怎样才能在应用程序中获得Future的实例? 两种最普通的资源是线程池和异步方法(线程池支持)。因此, startDownloading()方法可以被重写为:
- private final ExecutorService pool = Executors.newFixedThreadPool(10);
- public Future
startDownloading(final URL url) throws IOException { - return pool.submit(new Callable
() { - @Override
- public String call() throws Exception {
- try (InputStream input = url.openStream()) {
- return IOUtils.toString(input, StandardCharsets.UTF_8);
- }
- }
- });
- }
虽然有大量的繁琐的语法问题,但是基本思想是简单的: 把需要长时间运行的计算包装到可调用的
你还可以在Spring 和 EJB 碰上Future。比如Spring框架的中你可以为方法加入@Async的注解:
- @Async
- public Future
startDownloading(final URL url) throws IOException { - try (InputStream input = url.openStream()) {
- return new AsyncResult<>(
- IOUtils.toString(input, StandardCharsets.UTF_8)
- );
- }
- }
注意,我们简单地通过包装结果到AsyncResult来实现Future,但是这个方法本身不会与线程池交互或者异步处理。稍后 Spring会代理所有的调用来startDownloading()并在线程池中执行。 在EJB中,相同的特性通过加@Asynchronousannotation 来完成。
我们学到了许多java.util.concurrent.Future的知识。 现在我们不得不承认,接口非常有限,特别是在和其它语言作对比的时候。稍后介绍更多。
你是否不熟悉java 7 中的 try-with-resources Future 模式?那现在最好是迁移到java7上。java 6 在未来2周后将不再维护更新。
原文链接:http://www.oschina.net/translate/java-util-concurrent-future-basics
分享题目:java.util.concurrent.Future类基础
网页URL:http://www.shufengxianlan.com/qtweb/news39/289039.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联