我惊了!CompletableFuture居然有性能问题!

Runtime.getRuntime().availableProcessors()方法在Docker容器中遇到的问题和解决方案 问题 最近在线上环境遇到一个奇怪的问题,仅仅20qps的压测,产生非常多的毛刺,立刻判断出毛刺是由于YGC导致。 线上环境为docker容器,4核8G内存,openjdk8u 排查过程 于是登录线上机器查看GC日志,发现GC Workers: 63,但压测服务器仅4核,不可能有63个GC线程。 [GC pause (G1 Evacuation Pause) (young), 0.0054131 secs] 10 [Parallel Time: 3.6 ms, GC Workers: 63] 11 阅读详情

国庆的时候闲来无事,就随手写了一点之前说的比赛的代码,目标就是保住前 100 混个大赛的文化衫就行了。

现在还混在前 50 的队伍里面,稳的一比。

其实我觉得大家做柔性负载均衡那题的思路其实都不会差太多,就看谁能把关键的信息收集起来并利用上了。

由于是基于 Dubbo 去做的嘛,调试的过程中,写着写着我看到了这个地方:

org.apache.dubbo.rpc.protocol.AbstractInvoker#waitForResultIfSync

先看我框起来的这一行代码,aysncResult 的里面有有个 CompletableFuture ,它调用的是带超时时间的 get() 方法,超时时间是 Integer.MAX_VALUE,理论上来说效果也就等同于 get() 方法了。

从我直观上来说,这里用 get() 方法也应该是没有任何毛病的,甚至更好理解一点。

但是,为什么没有用 get() 方法呢?

其实方法上的注释已经写到原因了,就怕我这样的人产生了这样的疑问:

抓住我眼球的是这这几个单词:

have serious performance drop。

性能严重下降。

大概就是说我们必须要调用 java.util.concurrent.CompletableFuture#get(long, java.util.concurrent.TimeUnit) 而不是 get() 方法,因为 get 方法被证明会导致性能严重的下降。

对于 Dubbo 来说, waitForResultIfSync 方法,是主链路上的方法。我个人觉得保守一点说,可以说 90% 以上的请求都会走到这个方法来,阻塞等待结果。所以如果该方法如果有问题,则会影响到 Dubbo 的性能。

Dubbo 作为中间件,有可能会运行在各种不同的 JDK 版本中,对于特定的 JDK 版本来说,这个优化确实是对于性能的提升有很大的帮助。

就算不说 Dubbo ,我们用到 CompletableFuture 的时候,get() 方法也算是我们常常会用到的一个方法。

另外,这个方法的调用链路我可太熟悉了。

因为我两年前写的第一篇公众号文章就是探讨 Dubbo 的异步化改造的,《Dubbo 2.7新特性之异步化改造》

当年,这部分代码肯定不是这样的,至少没有这个提示。

因为如果有这个提示的话,我肯定第一次写的时候就注意到了。

果然,我去翻了一下,虽然图片已经很模糊了,但是还是能隐约看到,之前确实是调用的 get() 方法:

我还称之为最“骚”的一行代码。

因为这一行的代码就是 Dubbo 异步转同步的关键代码。

前面只是一个引子,本文不会去写 Dubbo 相关的知识点。

主要写写 CompletableFuture 的 get() 到底有啥问题。

放心,这个点面试肯定不考。只是你知道这个点后,恰好你的 JDK 版本是没有修复之前的,写代码的时候可以稍微注意一下。

学 Dubbo 在方法调用的地方加上一样的 NOTICE,直接把逼格拉满。等着别人问起来的时候,你再娓娓道来。

或者不经意间看到别人这样写的时候,轻飘飘的说一句:这里有可能会有性能问题,可以去了解一下。

啥性能问题?

根据 Dubbo 注释里面的这点信息,我也不知道啥问题,但是我知道去哪里找问题。

这种问题肯定在 openJDK 的 bug 列表里面记录有案,所以第一站就是来这里搜索一下关键字:

https://bugs.openjdk.java.net/projects/JDK/issues/

一般来说,都是一些陈年老 BUG,需要搜索半天才能找到自己想要的信息。

但是,这次运气好到爆棚,弹出来的第一个就是我要找的东西,简直是搞的我都有点不习惯了,这难道是传说中的国庆献礼吗,不敢想不敢想。

标题就是:对CompletableFuture的性能改进。

里面提到了编号为 8227019 的 BUG。

https://bugs.openjdk.java.net/browse/JDK-8227019

我们一起看看这个 BUG 描述的是啥玩意。

标题翻译过来,大概意思就是说 CompletableFuture.waitingGet 方法里面有一个循环,这个循环里面调用了 Runtime.availableProcessors 方法。且这个方法被调用的很频繁,这样不好。

在详细描述里面,它提到了另外的一个编号为 8227006 的 BUG,这个 BUG 描述的就是为什么频繁调用 availableProcessors 不太好,但是这个我们先按下不表。

先研究一下他提到的这样一行代码:

 spins = (Runtime.getRuntime().availableProcessors() > 1) ?
                    1 << 8 : 0; // Use brief spin-wait on multiprocessors

他说位于 waitingGet 里面,我们就去看看到底是怎么回事嘛。

但是我本地的 JDK 的版本是 1.8.0_271,其 waitingGet 源码是这样的:

java.util.concurrent.CompletableFuture#waitingGet

先不管这几行代码是啥意思吧,反正我发现没有看到 bug 中提到的代码,只看到了 spins=SPINS ,虽然 SPINS 调用了 Runtime.getRuntime().availableProcessors() 方法,但是该字段被 static 和 final 修饰了,也就不存在 BUG 中描述的“频繁调用”了。

于是我意识到我的版本是不对的,这应该是被修复之后的代码,所以去下载了几个之前的版本。

最终在 JDK 1.8.0_202 版本中找到了这样的代码:

和前面截图的源码的差异就在于前者多了一个 SPINS 字段,把 Runtime.getRuntime().availableProcessors() 方法的返回缓存了起来。

我一定要找到这行代码的原因就是要证明这样的代码确实是在某些 JDK 版本中出现过。

好了,现在我们看一下 waitingGet 方法是干啥的。

首先,调用 get() 方法的时候,如果 result 还是 null 那么说明异步线程执行的结果还没就绪,则调用 waitingGet 方法:

而来到 waitingGet 方法,我们只关注 BUG 相关这两个分支判断:

首先把 spins 的值初始化为 -1。

然后当 result 为 null 的时候,就一直进行 while 循环。

所以,如果进入循环,第一次一定会调用 availableProcessors 方法。然后发现是多处理器的运行环境,则把 spins 置为 1<<8 ,即 256。

然后再次进行循环,走入到 spins>0 的分支判断,接着做一个随机运算,随机出来的值如果大于等于 0 ,则对 spins 进行减一操作。

只有减到 spins 为 0 的时候才会进入到后面的这些被我框起来的逻辑中:

也就是说这里就是把 spins 从 256 减到 0,且由于随机函数的存在,循环次数一定是大于 256 次的。

但是还有一个大前提,那就是每次循环的时候都会去判断循环条件是否还成立。即判断 result 是否还是 null。为 null 才会继续往下减。

所以,你说这段代码是在干什么事儿?

其实注释上已经写的很清楚了:

Use brief spin-wait on multiprocessors。

brief,这是一个四级词汇哈,得记住,要考的。就是“短暂”的意思,是一个不规则动词,其最高级是 briefest。

对了,spin 这个单词大家应该认识吧,前面忘记给大家教单词了,就一起讲了,看小黑板:

所以注释上说的就是:如果是多处理器,则使用短暂的自旋等待一下。

从 256 减到 0 的过程,就是这个“brief spin-wait”。

但是仔细一想,在自旋等待的这个过程中,availableProcessors 方法只是在第一次进入循环的时候调用了一次。

那为什么说它耗费性能呢?

是的,确实是调用 get() 方法的只调用了一次,但是你架不住 get() 方法被调用的地方多啊。

就拿 Dubbo 举例,绝大部分情况下的大家的调用方式都用的是默认的同步调用的方案。所以每一次调用都会到异步转同步这里阻塞等待结果,也就说每次都会调用一次 get() 方法,即 availableProcessors 方法就会被调用一次。

那么解决方案是什么呢?

在前面我已经给大家看了,就是把 availableProcessors 方法的返回值找个字段给缓存起来:

但是后面跟了一个“problem”,这个“problem”就是说如果我们把多处理器这个值缓存起来了,假设程序运行的过程中出现了从多处理器到单处理器的运行环境变化这个值就不准确了,虽然这是一个不太可能的变化。但是即使这个“problem”真的发生了也没有关系,它只是会导致一个小小的性能损失。

所以就出现了前面大家看到的这样的代码,这就是 “we can cache this value in a field”:

而体现到具体的代码变更是这样的:

http://cr.openjdk.java.net/~shade/8227018/webrev.01/src/share/classes/java/util/concurrent/CompletableFuture.java.udiff.html

所以,当你去看这部分源码的时候,你会看到 SPINS 字段上其实还有很长一段话,是这样的:

给大家翻译一下:

1.在 waitingGet 方法中,进行阻塞操作前,进行旋转。

2.没有必要在单处理器上进行旋转。

3.调用 Runtime.availableProcessors 方法的成本是很高的,所以在此缓存该值。但是这个值是首次初始化时可用的 CPU 的数量。如果某系统在启动时只有一个 CPU 可以用,那么 SPINS 的值会被初始化为 0,即使后面再使更多的 CPU 在线,也不会发生变化。

当你有了前面的 BUG 的描述中的铺垫之后,你就明白了为什么这里写上了这么一大段话。

有的同学就真的去翻代码,也许你看到的是这样的:

什么情况?根本就看不到 SPINS 相关的代码啊,这不是欺骗老实人吗?

你别慌啊,猴急猴急的,我这不是还没说完嘛?

我们再把目光放到图片中的这句话上:

只需要在 JDK 8 中进行这个修复即可,因为 JDK 9 和更高版本的代码都不是这样的写的了。

比如在 JDK 9 中,直接拿掉了整个 SPINS 的逻辑,不要这个短暂的自旋等待了:

http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/f3af17da360b

虽然,拿掉了这个短暂的自旋等待,但是其实也算是学习了一个骚操作。

问:怎么在不引入时间的前提下,做出一个自旋等待的效果?

答案就是被拿掉的这段代码。

但是有一说一,我第一次看到这个代码的时候我就觉得别扭。这一个短短的自旋能延长多少时间呢?

加入这个自旋,是为了稍晚一点执行后续逻辑中的 park 代码,这个稍重一点的操作。但是我觉得这个 “brief spin-wait” 的收益其实是微乎其微的。

所以我也理解为什么后续直接把这一整坨代码拿掉了。而拿掉这一坨代码的时候,其实作者并没有意识到这里有 BUG。

而这里提到的作者,其实就是 Doug Lea 老爷子。

我为什么这样说呢?

依据就在这个 BUG 链接里面提到的编号为 8227018 的 BUG 中,它们其实描述的是同一个事情:

这里面有这样一段对话,出现了 David Holmes 和 Doug Lea:

Holmes 在这里面提到了 “cache this value in a field” 的解决方案,并得到了 Doug 的同意。

Doug 说: JDK 9 已经不用 spin 了。

所以,我个人理解是 Doug 在不知道这个地方有 BUG 的情况下,拿掉了 SPIN 的逻辑。至于是出于什么考虑,我猜测是收益确实不大,且代码具有一定的迷惑性。还不如拿掉之后,理解起来直观一点。

Doug Lea 大家都耳熟能详, David Holmes 是谁呢?

《Java 并发编程实战》的作者之一,端茶就完事了。

而你要是对我以前的文章印象足够深刻,那么你会发现早在《Doug Lea在J.U.C包里面写的BUG又被网友发现了。》这篇文章里面,他就已经出现过了:

老朋友又出现了,建议铁汁们把梦幻联动打在公屏上。

到底啥原因?

前面噼里啪啦的说了这么大一段,核心思想其实就是 Runtime.availableProcessors 方法的调用成本高,所以在 CompletableFuture.waitingGet 方法中不应该频繁调用这个方法。

但是 availableProcessors 为什么调用成本就高了,依据是啥,得拿出来看看啊!

这一小节,就给大家看看依据是什么。

依据就在这个 BUG 描述中:

https://bugs.openjdk.java.net/browse/JDK-8227006

标题上说:在 linux 环境下,Runtime.availableProcessors 执行时间增加了 100 倍。

增加了 100 倍,肯定是有两个不同的版本的对比,那么是哪两个版本呢?

在 1.8b191 之前的 JDK 版本上,下面的示例程序可以实现每秒 400 多万次对 Runtime.availableProcessors 的调用。

但在 JDK build 1.8b191 和所有后来的主要和次要版本(包括11)上,它能实现的最大调用量是每秒4万次左右,性能下降了100倍。

这就导致了 CompletableFuture.waitingGet 的性能问题,它在一个循环中调用了 Runtime.availableProcessors。因为我们的应用程序在异步代码中表现出明显的性能问题,waitingGet 就是我们最初发现问题的地方。

测试代码是这样的:

  public static void main(String[] args) throws Exception {
        AtomicBoolean stop = new AtomicBoolean();
        AtomicInteger count = new AtomicInteger();

        new Thread(() -> {
            while (!stop.get()) {
                Runtime.getRuntime().availableProcessors();
                count.incrementAndGet();
            }
        }).start();

        try {
            int lastCount = 0;
            while (true) {
                Thread.sleep(1000);
                int thisCount = count.get();
                System.out.printf("%s calls/sec%n", thisCount - lastCount);
                lastCount = thisCount;
            }
        }
        finally {
            stop.set(true);
        }
    }

按照 BUG 提交者的描述,如果你在 64 位的 Linux 上,分别用 JDK 1.8b182 和 1.8b191 版本去跑,你会发现有近 100 倍的差异。

至于为什么有 100 倍的性能差异,一位叫做 Fairoz Matte 的老哥说他调试了一下,定位到问题出现在调用 “OSContainer::is_containerized()” 方法的时候:

而且他也定位到了问题出现的最开始的版本号是 8u191 b02,在这个版本之后的代码都会有这样的问题。

带来问题的那次版本升级干的事是改进 docker 容器检测和资源配置的使用。

所以,如果你的 JDK 8 是 8u191 b02 之前的版本,且系统调用并发非常高,那么恭喜你,有机会踩到这个坑。

然后,下面几位大佬基于这个问题给出了很多解决方案,并针对各种解决方案进行讨论。

有的解决方案,听起来就感觉很麻烦,需要编写很多的代码。

最终,大道至简,还是选择了实现起来比较简单的 cache 方案,虽然这个方案也有一点瑕疵,但是出现的概率非常低且是可以接受的。

再看get方法

现在我们知道了这个没有卵用的知识点之后,我们再看看为什么调用带超时时间的 get() 方法,没有这个问题。

java.util.concurrent.CompletableFuture#get(long, java.util.concurrent.TimeUnit)

首先可以看到内部调用的方法都不一样了:

有超时时间的 get() 方法,内部调用的是 timedGet 方法,入参就是超时时间。

点进 timedGet 方法就知道为什么调用带超时时间的 get() 方法没有问题了:

在代码的注释里面已经把答案给你写好了:我们故意不在这里旋转(像waitingGet那样),因为上面对 nanoTime() 的调用很像一个旋转。

可以看到在该方法内部,根本就没有对 Runtime.availableProcessors 的调用,所以也就不存在对应的问题。

现在,我们回到最开始的地方:

那么你说,下面的 asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS) 如果我们改成 asyncResult.get() 效果还是一样的吗?

肯定是不一样的。

再说一次:Dubbo 作为开源的中间件,有可能会运行在各种不同的 JDK 版本中,且该方法是它主链路上的核心代码,对于特定的 JDK 版本来说,这个优化确实是对于性能的提升有很大的帮助。

所以写中间件还是有点意思哈。

最后,再送你一个为 Dubbo 提交源码的机会。

在其下面的这个类中:

org.apache.dubbo.rpc.AsyncRpcResult

还是存在这两个方法:

但是上面的 get() 方法只有测试类在调用了:

完全可以把它们全部改掉调用 get(long timeout, TimeUnit unit) 方法,然后把 get() 方法直接删除了。

我觉得肯定是能被 merge 的。

如果你想为开源项目做贡献,熟悉一下流程,那么这是一个不错的小机会。

CompletableFuture使用不当的生产问题记录 1 阅读详情

相关推荐

CompletableFuture是如何提升Future性能的

场景2:创建三个 Future,f1需要20s,f2需要5s,f3需要10s,然后我们将他们list.add(f1);list.add(f3),再依次fx.get(),你会发现,即使f2先执行完,也要等f1执行完,f2.get才能返回。如上代码,可以看到,第二个 Future 需要等待第一个 Future的返回值,而且第一个 Future 的返回值是在主线程中阻塞获取的。Future优点在于我们可以异步地进行一些非常密集的计算,而不会阻塞当前的线程,这样,我们在此期间就可以做一些其他的工作。

BASK2312的博客 585

Runtime.getRuntime().availableProcessors()

java.lang.Runtime.availableProcessors() 方法: 返回可用处理器的Java虚拟机的数量。 这个值可以在虚拟机中的某个调用过程中改变。应用程序是可用的处理器数量敏感,因此应该偶尔查询该属性,并适当调整自己的资源使用情况。方法声明:public native int availableProcessors();例子:package com.vrv.linkdo...

冯三思 4万+

【JAVA8】CompletableFuture使用详解

CompletableFuture!让你的代码免受阻塞之苦! 灵活的使用`CompletableFuture`可以让我们感受java8的异步编程之美!

胖虎儿的博客 1万+

常用API之Runtime

Runtime类被设置为private,不可以创建对象,想要调用需要通过getRuntime方法调用。Runtime表示当前虚拟机的运行环境。

buith9879的博客 1388

【C++】POCO学习总结(六):线程、线程池、同步

Poco::RunnableAdapter继承自Poco::Runnable,在Poco::RunnableAdapter构造函数中指定了类和方法;Poco::ThreadLocal是线程局部变量,也叫线程局部存储,意思是模版ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。

郭老二 5099

SAP CEWB 高效批量调整工艺路线与BOM的实战指南

本文详细介绍了SAP CEWB工具在批量调整工艺路线与BOM中的高效应用。通过实战案例和操作指南,帮助制造业企业快速掌握批量修改技巧,显著提升工作效率,避免手工操作带来的错误和耗时。特别适合需要频繁更新工艺路线和BOM的企业用户。

weixin_42524708的博客 397

我惊了!CompletableFuture居然有性能问题!(1)

标题翻译过来,大概意思就是说 CompletableFuture.waitingGet 方法里面有一个循环,这个循环里面调用了 Runtime.availableProcessors 方法。且这个方法被调用的很频繁,这样不好。在详细描述里面,它提到了另外的一个编号为 8227006 的 BUG,这个 BUG 描述的就是为什么频繁调用 availableProcessors 不太好,但是这个我们先按下不表。先研究一下他提到的这样一行代码:1

2401_84046895的博客 935

告别黑窗口!用VSCode+Native Debug调试C/C++程序,比GDB命令行舒服多了

本文介绍了如何使用VSCode配合Native Debug扩展来调试C/C++程序,替代传统的GDB命令行方式。通过可视化调试环境,开发者可以更高效地管理断点、查看变量和调用栈,大幅提升调试效率。文章详细讲解了环境配置、核心调试功能及高级技巧,帮助开发者快速上手这一现代调试工具。

weixin_26833139的博客 251

掌握CompletableFuture,提升你的代码效率!

本文将详细讲解CompletableFuture的使用方法及其在提升代码效率方面的优势。通过对CompletableFuture的核心功能、创建和组合异步任务的技巧进行深入探讨,读者将了解到如何利用这一工具简化复杂的异步编程,实现高效的非阻塞操作。本文还包括实际示例和最佳实践,帮助开发者优化代码结构,提高程序的性能和响应速度。掌握CompletableFuture,将显著提升你的代码效率和质量。

忆~遂愿的博客 1885

Stable Diffusion WebUI 安装前准备

大家好,我是水滴~~在安装 stable-diffusion-webui 前需要做一些准备工作,本篇文章主要介绍需要的电脑配置、魔法、安装 Python、安装 Git 等。

水滴的博客 2100

大数据在电力行业的应用案例解析-【电力技术】(九)大数据在电力储能运维中的深度应用(含故障预测代码)

大数据技术为电力储能运维提供了“精准化、智能化、高效化”的解决方案,破解了传统运维的核心痛点,实现了储能系统从“被动抢修”到“主动运维”的转型,为新型电力系统建设提供了重要支撑。当前,随着储能产业的快速发展,大数据与储能运维的融合将更加深入,未来将结合人工智能、物联网、区块链等技术,实现储能运维的全流程智能化——从设备故障的提前预警,到寿命的精准预测,再到运维策略的自动优化、调度协同的实时响应,进一步提升储能系统的安全性、经济性与可靠性。

getusushu的博客 88

巧用CompletableFuture返回值解决性能瓶颈

巧用CompletableFuture返回值实现并发需求背景CompletableFuture\需求背景 对一组字符串数据进行处理,处理逻辑简单封装一个对象,包装该字符串,最终汇总返回。 下面实现只使用CompleteableFuture,其它方式如paraStream不考虑。 CompletableFuture<Void>实现 考虑到性能,对于字符串的处理可以进行并发。实现如下: ...

sunquan291的专栏 8281

GEE:连续变化检测 CCD 第一步(导出ee.Algorithms.TemporalSegmentation.Ccdc函数的结果)

连续变化检测与分类(Continuous Change Detection and Classification, CCDC)主要有两个组件,一个连续变化检测 CCD,另外一个分类。在 Google Earth Engine (GEE)平台上进行 CCD 时间序列变化检测的时候,为了防止内存超限问题,将代码分为2阶段执行。第一阶段是运行 `ee.Algorithms.TemporalSegmentation.Ccdc` 函数,本文将详细介绍 CCD 的第一阶段的代码。

养乐多的博客 2492

单线程、Callable、CompletableFuture性能比较,推荐使用CompletableFuture

在多线程合并返回结果时可以用到Callble,它和Runnable的作用差不多,Callabe可以返回结果。先面对单线程、callable、FutureTask的增强版CompletableFuture进行性能比较。 public static void main(String[] args) throws ExecutionException, InterruptedException { //单线程计算累加 Instant start = Instant.now();

qq_22744093的博客 1790

168、OIS光学防抖系统设计:陀螺仪标定、音圈马达驱动与滚珠式/悬丝式结构选型

本文总结了OIS光学防抖系统设计中的关键问题与解决方案。作者通过实际案例指出,陀螺仪标定需重视零偏、灵敏度和温度补偿问题,音圈马达驱动需采用电流环控制并优化相位补偿。在机械结构选型方面,滚珠式适合大角度补偿但存在回差问题,悬丝式精度高但受重力影响,需根据应用场景选择。系统联调建议从开环到闭环逐步验证,注意陀螺仪与驱动频率匹配。最后给出5条经验建议:关注陀螺仪信噪比而非分辨率、预留标定余量、重视机械结构公差、配备专业调试工具、协调OIS与电子防抖的分工配合。文章强调OIS调试需针对不同模组特性进行反复测试与标

zzfmlxs的博客 46

把静态前端托管进 SAP BTP:HTML5 Application Deployer 与企业级内容部署全攻略

本文介绍了在SAP BTP Cloud Foundry环境中使用HTML5 Application Repository托管前端静态资源的工程化实践。通过HTML5 Application Deployer工具,结合MTA描述、路由配置和服务实例,实现前后端解耦和标准化部署。文章详细阐述了目录结构、关键配置文件、MTA编排以及构建部署流程,并针对大体积前端资源提供了GACD和异步上传两种解决方案。最后说明了如何与AppRouter协同工作,使部署内容可供终端用户访问。这套方法使前端更新无需重启后端,支持团队

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 155

CompletableFuture使用教程

Java 8 CompletableFuture 教程 原文链接:https://www.callicoder.com/java-8-completablefuture-tutorial/ Java 8 有大量的新特性和增强如 Lambda 表达式,Streams,CompletableFuture等。在本篇文章中我将详细解释清楚CompletableFuture以及它所有方法的使用。 什么是CompletableFuture? 在Java中CompletableFuture用于异步编程,异步编程是编写

weixin_40719914的博客 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

CompletableFuture原理与用法

在Java中CompletableFuture用于异步编程,异步通常意味着非阻塞,运行任务单独的线程,与主线程隔离。并且通过回调可以在主线程中得到异步任务的执行状态,是否完成和异常等信息。通过这种方式,主线程不会被阻塞,不需要一直等到子线程完成。主线程可以并行的执行其他任务。使用这种并行方式,可以极大的提高程序的性能。CompletableFuture 可以从全局的 ForkJoinPool.commonPool() 获得一个线程中执行这些任务。

旷野历程 2384

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

手把手教学妹CompletableFuture异步化,性能关系直接起飞!

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

2401_84023482的博客 888

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

CompletableFuture优化接口性能案例

CompletableFuture优化接口性能案例需求背景解决方案 需求背景 在教育中心所有课程详情页都大致包含下面这么些,每种卡片的数据可能来自不同的数据源。数据源可能就是缓存数据,也可能是第三方的接口返回数据。因此对于这个接口一次性返回这么多卡片信息还是有点重的,我们尽量要使得每个卡片请求的数据要够快。对于头部影藏卡片而言,在数据适配阶段串行调用了三个第三方接口,而且每个接口最大超时时间outTime=200~300ms,对整个接口的性能还是有很大影响。 课程详情头部隐藏卡片,课程详情头部促销卡片, 课

qq_38553514的博客 1487

JAVA:异步任务处理类CompletableFuture让性能提升一倍

CompletableFuture异步编程详细介绍,包括supplyAsync、thenCompose 、whenComplete 。

永远保持随时离开的技术能力! 2665

CompletableFuture实战--优化性能提升

CompletableFuture 相比于jdk5所提出的future概念,future在执行的时候支持异步处理,但是在回调的过程中依旧是难免会遇到需要等待的情况。 在jdk8里面,出现了CompletableFuture的新概念,支持对于异步处理完成任务之后自行处理数据。当发生异常的时候也能按照自定义的逻辑来处理。 如何通过使用CompletableFuture提升查询的性能的问题呢? 下边我举...

Danny_idea的博客 1960

性能爆炸的多线程编排神器CompletableFuture

​ 使用CompletableFuture,程序员可以很方便的控制线程的执行顺序。包括串行、并行或者多个线程的组合与转化功能。​ CompletableFuture主要实现了两个关键接口:Future:Future是一个代表异步计算结果的对象。它允许你从一个异步操作中获取结果(一旦结果可用),取消正在执行的计算,或者检查计算是否已经完成。Future 通常与 ExecutorService 结合使用来提交任务,并且是 java.util.concurrent 包的一部分.

roykingw的专栏 1812

看完JDK并发包源码的这个性能问题,我惊了!

国庆的时候闲来无事,就随手写了一点之前说的比赛的代码,目标就是保住前 100 混个大赛的文化衫就行了。现在还混在前 50 的队伍里面,稳的一比。其实我觉得大家做柔性负载均衡那题的思路其实都...

架构师小秘圈 231

CompletableFuture

1.Future 1.1Future接口理论知识复习 1.2 FutureTask架构 1.3 Future编码实战 2.CompletableFuture 2.1 CompletableFuture对Future的改进 2.2案例精讲-从电商网站的比价需求说开去 2.3 CompletableFuture常用方法

qq_44300280的博客 2839
上一篇: 字节跳动 基础架构 一二三面面经。(虚拟化部门)
下一篇: 阿里限流神器Sentinel夺命连环 17 问?
在酒吧写代码
博客等级 码龄7年 210粉丝 330原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值