CompletableFuture不能被打断

我已经写了很多有关InterruptedException和中断线程的文章 。 简而言之,如果您没有Future.cancel()调用Future.cancel()那么Future将终止待处理的get() ,但还将尝试中断基础线程。 这是一个非常重要的功能,可以更好地利用线程池。 我还写信总是比标准Future更喜欢CompletableFuture 。 事实证明,功能更强大的Future弟兄没有那么优雅地处理cancel() 。 考虑以下任务,我们稍后将在整个测试中使用以下任务:

class InterruptibleTask implements Runnable {private final CountDownLatch started = new CountDownLatch(1)private final CountDownLatch interrupted = new CountDownLatch(1)@Overridevoid run() {started.countDown()try {Thread.sleep(10_000)} catch (InterruptedException ignored) {interrupted.countDown()}}void blockUntilStarted() {started.await()}void blockUntilInterrupted() {assert interrupted.await(1, TimeUnit.SECONDS)}}

客户端线程可以检查InterruptibleTask以查看其是否已开始或被中断。 首先,让我们看一下InterruptibleTask对外部的cancel()反应:

def "Future is cancelled without exception"() {given:def task = new InterruptibleTask()def future = myThreadPool.submit(task)task.blockUntilStarted()and:future.cancel(true)when:future.get()then:thrown(CancellationException)
}def "CompletableFuture is cancelled via CancellationException"() {given:def task = new InterruptibleTask()def future = CompletableFuture.supplyAsync({task.run()} as Supplier, myThreadPool)task.blockUntilStarted()and:future.cancel(true)when:future.get()then:thrown(CancellationException)
}

到目前为止,一切都很好。 显然, FutureCompletableFuture工作方式几乎相同-在取消结果后检索结果会引发CancellationException 。 但是myThreadPool线程呢? 我以为它会被游泳池打断,从而被回收,我怎么了!

def "should cancel Future"() {given:def task = new InterruptibleTask()def future = myThreadPool.submit(task)task.blockUntilStarted()when:future.cancel(true)then:task.blockUntilInterrupted()
}@Ignore("Fails with CompletableFuture")
def "should cancel CompletableFuture"() {given:def task = new InterruptibleTask()def future = CompletableFuture.supplyAsync({task.run()} as Supplier, myThreadPool)task.blockUntilStarted()when:future.cancel(true)then:task.blockUntilInterrupted()
}

第一个测试将普通的Runnable提交给ExecutorService并等待其启动。 稍后,我们取消Future并等待直到观察到InterruptedException 。 当基础线程被中断时, blockUntilInterrupted()将返回。 但是,第二次测试失败。 CompletableFuture.cancel()永远不会中断基础线程,因此尽管Future看起来好像已被取消,但后备线程仍在运行,并且sleep()不会抛出InterruptedException 。 错误或功能? 它已记录在案 ,因此很遗憾地提供一个功能:

参数: mayInterruptIfRunning –此值在此实现中无效,因为不使用中断来控制处理。

您说RTFM,但是为什么CompletableFuture这样工作? 首先,让我们研究“旧的” Future实现与CompletableFuture有何不同。 从ExecutorService.submit()返回的FutureTask具有以下cancel()实现(我使用类似的非线程安全Java代码删除了Unsafe ,因此仅将其视为伪代码):

public boolean cancel(boolean mayInterruptIfRunning) {if (state != NEW)return false;state = mayInterruptIfRunning ? INTERRUPTING : CANCELLED;try {if (mayInterruptIfRunning) {try {Thread t = runner;if (t != null)t.interrupt();} finally { // final statestate = INTERRUPTED;}}} finally {finishCompletion();}return true;
}

FutureTask具有一个遵循该状态图的state变量:

未来状态图

在的情况下, cancel()我们可以进入CANCELLED状态或去INTERRUPTED通过INTERRUPTING 。 核心部分是我们拿runner线程(如果存在的,也就是说,如果当前正在执行的任务),我们尽量打断它。 该分支负责急切和强制中断已运行的线程。 最后,我们必须通知阻塞的所有线程Future.get()finishCompletion()这里无关紧要)。 因此,很明显,多大的Future取消已经运行的任务。 那CompletableFuture呢? cancel()伪代码:

public boolean cancel(boolean mayInterruptIfRunning) {boolean cancelled = false;if (result == null) {result = new AltResult(new CancellationException());cancelled = true;}postComplete();return cancelled || isCancelled();
}

令人失望的是,我们几乎没有将result设置为CancellationException ,而忽略了mayInterruptIfRunning标志。 postComplete()也有类似的作用finishCompletion() -在通知未来注册的所有悬而未决的回调。 它的实现相当令人不快(使用非阻塞式Treiber stack ),但是它绝对不会中断任何底层线程。

原因和含义

CompletableFuture情况下,有限的cancel()不是错误,而是设计决定。 CompletableFuture并非固有地绑定到任何线程,而Future几乎总是代表后台任务。 从零开始创建CompletableFuturenew CompletableFuture<>() )是完美的,其中根本没有要取消的底层线程。 我仍然不禁感到大多数CompletableFuture 都将具有关联的任务和后台线程。 在这种情况下, cancel()可能会出现故障。 我不再建议用CompletableFuture盲目地替换Future ,因为它可能会更改依赖cancel()的应用程序的行为。 这意味着CompletableFuture故意违反了Liskov替换原则 -这是需要考虑的严重问题。

翻译自: https://www.javacodegeeks.com/2015/03/completablefuture-cant-be-interrupted.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nginx 禁止部分 User-Agrent 访问

经常有一些垃圾爬虫&#xff0c;完全不管你受得了受不了&#xff0c;完全不管你的 robots.txt &#xff0c;拼命的爬你的网站&#xff0c;用下面方面可以帮这帮垃圾干掉。 location / { root /home/www/; if ($http_user_agent ~* "qihoobot") { retu…

crio电压采集 labview_NI cDAQ917采集温度方法

NI cDAQ-9171是一款由总线供电的单槽NI CompactDAQ USB机箱&#xff0c;适合较小的便携式传感器测量系统。cDAQ-9171可与50多款专用测量模块配合使用&#xff0c;用于构建模拟输出、数字I/O或计数器/定时器测量系统。这些模块适用于各种传感器测量&#xff0c;包括热电偶、RTD、…

JPA 2.1如何成为新的EJB 2.0

美丽在于情人眼中。 “轻松”也是如此&#xff1a; 了解有关SQL结果集映射的更多信息&#xff0c;并轻松处理本机查询结果&#xff1a; http : //t.co/WH4BTlClIP #JPA #Java #JavaEE — Thorben Janssen&#xff08; thjanssen123&#xff09; 2015年4月15日 Thorben撰写了…

常见问题摘要(生活篇)

1 lingoes软件安装了&#xff0c;却没发现怎么取词&#xff1f; 答&#xff1a;在软件设置里面&#xff0c;修改取词模式&#xff0c;一般以鼠标左键按下ctrl 为标准操作。转载于:https://www.cnblogs.com/lastshadow/p/3330146.html

android finish 区别,Android Activity类finish、onDestory和System.exit介绍

image.pngfinish函数Activity.finish()Call this when your activity is done and should be closed.在你的activity动作完成的时候&#xff0c;或者Activity需要关闭的时候&#xff0c;调用此方法。当调用此方法的时候&#xff0c;系统只是将最上面的Activity移出了栈&#xf…

github哪些协议能商用_GitHub 上有哪些一般人也可以用的项目?

​之前有不少粉丝来信询问&#xff1a;能否给初步接触 GitHub 的用户&#xff0c;推荐几个比较实用、容易看懂&#xff0c;无需具备太多专业知识便能上手使用的项目呢&#xff1f;答案是&#xff1a;有的。今天&#xff0c;我们就上述问题&#xff0c;来聊聊 GitHub 上有哪几个…

在JVM中记录世界停顿

不同的事件可能导致JVM暂停所有应用程序线程。 这种暂停称为世界停止&#xff08;STW&#xff09;暂停。 触发STW暂停的最常见原因是垃圾回收&#xff08; 例如github中的示例 &#xff09;&#xff0c;但是不同的JIT操作&#xff08; 示例 &#xff09;&#xff0c;偏向锁吊销…

目睹鸿蒙开创四大至高位面,吞噬星空 绝非鸿蒙系列,完结前最后的分析【申精】...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼先说说空间的划分&#xff1a;第一要说的是空间等级的划分&#xff0c;盘龙里分的很清楚&#xff0c;物质位面&#xff0c;七大神位面&#xff0c;四大至高位面&#xff0c;说得很清楚&#xff0c;物质位面虽然是最低等的位面&…

小程序确定取消弹窗_小程序开发之弹出框

小程序开发过程中&#xff0c;很多地方为了便利我们多采用小程序自带弹出框来实现交互效果。这也够大多数开发使用&#xff0c;下面我给大家详细介绍下小程序弹出框wx.showToast()title&#xff1a;显示的提示信息&#xff0c;在没有图标的情况下&#xff0c;文本内容可显示两行…

jOOQ与Hibernate:何时选择哪个

Hibernate已成为Java生态系统中的事实上的标准&#xff0c;事实上&#xff0c; 如果标准对您很重要 &#xff0c;并且如果您将JCP与ISO&#xff0c;ANSI&#xff0c;IEEE等置于同一级别&#xff0c;那么Hibernate也是实际的JavaEE标准实现。 本文的目的不是讨论标准&#xff0…

【IE6的疯狂之四】IE6文字溢出BUG

在IE6下使用浮动可能会出现文字重复的情况. 在IE6下&#xff0c;浮动层之间有注释文字的话&#xff0c;之前那个浮动层的内容文字就有可能遭遇一个“隐形”的复制&#xff0c;但是代码里查看文字可并没有多出来。 看个例子&#xff1a; XML/HTML代码<!DOCTYPE html PUBLIC ”…

html中左侧播放器插件,简洁实用的html5音乐播放器插件

js代码window.onload function(){MC.music({hasAjax:false,left:50%,bottom:50%,musicChanged:function(ret){// alert(ret.url);// getMusic_buffer(ret.url);// return;var data ret.data;var index ret.index;var imageUrl data[index].img_url;var music_bg document.…

linux怎么才能算telnet成功_怎么表白才算成功呢

要怎样表白才算成功呢&#xff1f;其实如果对方也有点喜欢你的&#xff0c;对你有点感觉的&#xff0c;不管怎样表白&#xff0c;你都会成功的&#xff0c;相反&#xff0c;如果对方本身就对你没感觉的&#xff0c;不管你要怎么轰轰烈烈的表白&#xff0c;你都不会成功。下面&a…

我们真的仍然需要32位JVM吗?

即使到了今天&#xff08;2015年&#xff09;&#xff0c;我们仍然有两个版本或Oracle HotSpot JDK –已调整为32或64位体系结构。 问题是我们是否真的想在服务器甚至笔记本电脑上使用32位JVM&#xff1f; 我们应该有很受欢迎的意见&#xff01; 如果只需要较小的堆&#xff0c…

html js点击字图片下拉,JavaScript实现文字与图片拖拽效果的方法

本文实例讲述了JavaScript实现文字与图片拖拽效果的方法。分享给大家供大家参考。具体实现方法如下&#xff1a;JavaScript实现文字与图片的拖拽效果*{padding:0;margin:0;}.tips{position:absolute;background:#eee;}图片可以拖动脚本之家拖动链接也可以var $idfunction(id){r…

ccf命令行选项只能用c实现_CCF-201403-3-命令行选项

问题描述试题编号&#xff1a;201403-3试题名称&#xff1a;命令行选项时间限制&#xff1a;1.0s内存限制&#xff1a;256.0MB问题描述&#xff1a;问题描述请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项。每个命令行由若干个字符串组成,它们之间恰好由一个空格…

python data frame_Python dataframer包_程序模块 - PyPI - Python中文网

数据框尝试将任何文件加载到pandas数据帧中&#xff0c;以最少的配置&#xff0c;关注生物信息学示例通常&#xff0c;您将从磁盘读取文件(open(my-file.txt, rb))。但是字节流在这里更简单。>>> from io import BytesIO>>> from dataframer import datafram…

html设置页面的高度和宽度,web显示页面有图像上设置高度和宽度很重要

因此即使浏览器只有HTML&#xff0c;它仍然能够分配适当的空间。所以我们可以修改成以下内容&#xff1a;最近我们发现谷歌浏览器对图片设置有一定的修改&#xff0c;它主要在图像上进行设置width和设置height属性&#xff0c;以防止布局发生变化并改善网站访问者的体验。Web性…

lsnrctl 与 tnsnames.ora 的联系

平台&#xff1a;Windoxs XPOracle 11G 当使用oralce的 Net Manager创建了一个名为“L3”的Listener后&#xff0c;要想使用lsnrctl启动和关闭 L3 还必须在tnsnames.ora 中配置一个名为L3的条目. listener.ora L3 (DESCRIPTION (ADDRESS (PROTOCOL TCP)(HOST princess…

Java EE,Docker和Maven(技术提示#89)

Java EE应用程序通常使用Maven构建和打包。 例如&#xff0c; github.com/javaee-samples/javaee7-docker-maven是一个普通的Java EE 7应用程序&#xff0c;它显示了Java EE 7依赖性&#xff1a; <dependencies><dependency><groupId>javax</groupId>…