java.util.concurrent.Future基础
在此,我开始撰写一系列有关编程语言中的未来概念(也称为promise或delays )的文章,标题为: Back to the Future 。 由于对异步,事件驱动,并行和可伸缩系统的需求不断增长,所以期货是非常重要的抽象,如今比以往任何时候都更加重要。 在第一篇文章中,我们将发现最基本的java.util.concurrent.Future<T>
接口。 稍后,我们将跳入其他框架,库甚至语言。 Future<T>
是相当有限的,但必须了解,ekhm,将来部分。
在单线程应用程序中,当您调用方法时,它仅在计算完成IOUtils.toString()
返回( IOUtils.toString()
来自Apache Commons IO ):
public String downloadContents(URL url) throws IOException {try(InputStream input = url.openStream()) {return IOUtils.toString(input, StandardCharsets.UTF_8);}
}//...final String contents = downloadContents(new URL("http://www.example.com"));
downloadContents()
看起来是无害的1 ,但它甚至可能需要花费很长时间才能完成。 此外,为了减少延迟,您可能希望在等待结果的同时进行其他独立的处理。 在过去,您将启动一个新Thread
并以某种方式等待结果(共享内存,锁,可怕的wait()
/ notify()
对等),使用Future<T>
会更加愉快:
public static Future<String> startDownloading(URL url) {//...
}final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com"));
//other computation
final String contents = contentsFuture.get();
我们将很快实现startDownloading()
。 目前,重要的是要了解这些原理。 startDownloading()
不阻塞,等待外部网站。 相反,它会立即返回,并返回轻量级的Future<String>
对象。 此对象保证 String
将来会可用。 不知道什么时候,但是保留此引用,一旦存在,您就可以使用Future.get()
检索它。 换句话说, Future
是一个尚未存在的对象的代理或包装。 异步计算完成后,您可以提取它。 那么Future
提供了什么API?
Future.get()
是最重要的方法。 它阻塞并等待,直到承诺的结果可用(已解决 )。 因此,如果我们确实需要该String
,则只需调用get()
并等待。 有一个过载的版本可以接受超时,所以一旦出现问题,您将不会永远等待。 如果等待时间太长,则会抛出TimeoutException
。
在某些用例中,您可能希望窥视“ Future
,如果结果尚不可用,请继续。 使用isDone()
可以做到这一点。 想象一下这样一种情况,您的用户正在等待一些异步计算,而您想让他知道我们仍在等待并同时进行一些计算:
final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com"));
while (!contentsFuture.isDone()) {askUserToWait();doSomeComputationInTheMeantime();
}
到最后调用contentsFuture.get()
是保证立即返回,而不是因为块Future.isDone()
返回true
。 如果遵循上述模式,请确保您不忙于等待,每秒每秒调用isDone()
数百万次。
取消期货是我们尚未讨论的最后一个方面。 想象一下,您开始了一些异步作业,并且您只能在给定的时间内等待它。 如果2秒钟后仍没有出现,我们会放弃并传播错误或解决它。 但是,如果您是一个好公民,您应该以某种方式告诉这个未来的目标:我不再需要您,那就算了。 通过不运行过时的任务来节省处理资源。 语法很简单:
contentsFuture.cancel(true); //meh...
我们都喜欢神秘的布尔参数,不是吗? 取消有两种口味。 通过将false
传递给mayInterruptIfRunning
参数,当Future
表示尚未开始的计算结果时,我们仅取消尚未开始的任务。 但是,如果我们的Callable.call()
已经在中间,则让它结束。 但是,如果我们传递true
,则Future.cancel()
将更具攻击性,并尝试中断已经在运行的作业。 怎么样? 考虑所有引发臭名昭著的InterruptedException
方法,即Thread.sleep()
, Object.wait()
, Condition.await()
以及许多其他方法(包括Future.get()
)。 如果您禁止使用任何此类方法,而某人决定取消您的Callable
,则它们实际上将抛出InterruptedException
,表示有人试图中断当前正在运行的任务。
因此,我们现在了解什么是Future<T>
–将来会得到的东西的占位符。 这就像尚未生产的汽车的钥匙。 但是,实际上如何在应用程序中获取Future<T>
的实例? 两种最常见的来源是线程池和异步方法(由您的线程池支持)。 因此,我们的startDownloading()
方法可以重写为:
private final ExecutorService pool = Executors.newFixedThreadPool(10);public Future<String> startDownloading(final URL url) throws IOException {return pool.submit(new Callable<String>() {@Overridepublic String call() throws Exception {try (InputStream input = url.openStream()) {return IOUtils.toString(input, StandardCharsets.UTF_8);}}});
}
语法很多,但基本思想很简单:将长时间运行的计算包装在Callable<String>
然后submit()
它们submit()
到10个线程的线程池中。 提交返回Future<String>
某些实现,最有可能以某种方式链接到您的任务和线程池。 显然,您的任务不会立即执行。 而是将其放置在队列中,该队列稍后(甚至可能更晚)由池中的线程轮询。 现在应该清楚这两种cancel()
含义–您始终可以取消仍然驻留在该队列中的任务。 但是取消已经运行的任务要复杂一些。
可以遇到Future
另一个地方是Spring和EJB。 例如,在Spring框架中,您可以使用@Async
注释您的方法 :
@Async
public Future<String> startDownloading(final URL url) throws IOException {try (InputStream input = url.openStream()) {return new AsyncResult<>(IOUtils.toString(input, StandardCharsets.UTF_8));}
}
注意,我们只是将结果包装在实现Future
AsyncResult
。 但是该方法本身不处理线程池或异步处理。 Spring稍后将代理所有对startDownloading()
调用,并在线程池中运行它们。 EJB中的@Asynchronous
批注提供了完全相同的功能。
因此,我们了解了很多有关java.util.concurrent.Future
。 现在该承认了–该界面非常有限,尤其是与其他语言相比时。 以后再说。
1 –您不熟悉Java 7的try-with-resources功能吗? 您现在最好切换到Java 7。 Java 6将在两周内不再维护。
参考: NoBlogDefFound博客上来自我们的JCG合作伙伴 Tomasz Nurkiewicz的java.util.concurrent.Future基础 。
翻译自: https://www.javacodegeeks.com/2013/02/java-util-concurrent-future-basics.html
java.util.concurrent.Future基础相关推荐
- java.util.concurrent包
本文是我们学院课程中名为Java Concurrency Essentials的一部分 . 在本课程中,您将深入探讨并发的魔力. 将向您介绍并发和并发代码的基础知识,并学习诸如原子性,同步和线程安全之 ...
- java.util.concurrent包API学习笔记
newFixedThreadPool 创建一个固定大小的线程池. shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭. awaitTermination():用于等待子线程结束, ...
- java.util.concurrent 包下面的所有类
java.util.concurrent 包下面的所有类 原子操作数类: java.util.concurrent.atomic.AtomicBoolean.class java.util.concu ...
- java.util.concurrent 编程范例
http://kanglecjr.iteye.com/blog/1070934 java.util.concurrent 范例之一 博客分类: Java JavaTomcatthread java.u ...
- 使用java.util.concurrent包处理多线程
出处:http://blog.csdn.net/hjl_168562/article/details/8158023 1.使用拥有固定的线程数的线程池执行线程任务 package com.justin ...
- java.util.concurrent 多线程框架
JDK5中的一个亮点就是将Doug Lea的并发库引入到Java标准库中.Doug Lea确实是一个牛人,能教书,能出书,能编码,不过这在国外还是比较普遍的,而国内的教授们就相差太远了. 一般的服务器 ...
- java.util.concurrent.ExecutorService 接口 源码
2019独角兽企业重金招聘Python工程师标准>>> 线程池相关 源码: package java.util.concurrent;import java.util.List; i ...
- JUC并发编程(java util concurrent)(哔站 狂神说java juc并发编程 摘录笔记)
JUC并发编程(java util concurrent) 1.什么是JUC JUC并不是一个很神秘的东西(就是 java.util 工具包.包.分类) 业务:普通的线程代码 Thread Runna ...
- 高并发编程基础(java.util.concurrent包常见类基础)
JDK5中添加了新的java.util.concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法 ...
最新文章
- 二维数组练习--矩阵的加法和乘法
- API 版本控制的几种方式
- Redis专题-持久化方式
- linux 查询替换文件内容吗,Linux 下查询文件的方法 替换文件内容
- python操作文件和目录_python文件和目录操作方法
- oracle无效的关联运算符,菜鸟请教:关联操作符=>用法
- 我的世界linux开服权限不足,我的世界路由器开服怎么获得超级管理员权限
- 【Linux】linux grep过滤中,不包含某些字符串
- python代码错误有哪些_在编写python代码时,小白最容易犯的十几个错误 !
- 绿地深蓝机器人_人工智能企业深兰科技获绿地控股3亿元战略投资
- html获取元素的rgb值,使用javascript提取支持的HTML或X11颜色名称及其RGB值的列表
- 电脑分屏没有声音_怎样解决qq屏幕分享没有声音问题
- ASUS RT-N16 刷番茄Tomato
- 数据库 case wen条件语句的运用
- 基础教学 | 什么是负载均衡?
- QCon 北京 2021:Pulsar PMC 成员翟佳出席并演讲
- Excel表格按行数拆分为多个文件
- mysql error :1114 - The table ‘XXX‘ is full
- RK平台 MPP 与RGA ,解码h265绿屏,花屏解决方法
- Linux 音频驱动(三) ASoC音频驱动之Codec驱动
热门文章
- 使用IDEA Maven搭建Mybatis环境
- dd命令打包多个文件_linux的tar命令详情;linux多个文件压缩打包到一个压缩文件...
- 小小涉及OpenFeign原理:Could not extract response: no suitable HttpMessageConverter found for response type
- HDU1231(最大连续子序列)
- javafx 调用java_Java验证(javafx)
- 高级java开发_我最喜欢的Java高级开发人员书籍
- Java Platform Module系统中的可选依赖项
- JavaOne 2016后续活动
- 微基准测试进入Java 9
- AutoValue:生成的不可变值类